From 32e19d94afd1fbfe93f023ffa1084bdb4f39fd75 Mon Sep 17 00:00:00 2001 From: Lyndon Jetten Date: Wed, 17 Feb 2021 16:59:26 +0100 Subject: [PATCH] =?UTF-8?q?Weiterentwicklung=20am=20Quittierungsbelegfeatu?= =?UTF-8?q?re=20im=20Mobilklienten=20Mehrt=C3=A4gige=20Buchungen=20werden?= =?UTF-8?q?=20im=20Mobilklienten=20korrekt=20gespeichert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BeWo/ServiceProxy/Generated.cs | 159 +- BeWoPlanerMobil/App_Start/BundleConfig.cs | 8 +- BeWoPlanerMobil/BeWoPlanerMobil.csproj | 3 +- BeWoPlanerMobil/Controllers/MainController.cs | 46 +- .../Controllers/ReportController.cs | 409 ++--- BeWoPlanerMobil/Models/ReportModel.cs | 9 + BeWoPlanerMobil/Scripts/mobileUtils.js | 15 +- BeWoPlanerMobil/Scripts/modernizr-2.8.3.js | 1406 ----------------- BeWoPlanerMobil/Scripts/view-scripts/main.js | 10 +- .../Scripts/view-scripts/report.js | 239 +-- .../Util/QuittierungsbelegResult.cs | 11 +- .../ReportUtils/ConfirmationReceiptObject.cs | 28 +- BeWoPlanerMobil/Views/Report/Report.cshtml | 236 ++- BeWoPlanerMobil/Views/Shared/_Layout.cshtml | 5 +- BeWoPlanerMobil/Web.config | 6 +- BeWoPlanerMobil/packages.config | 1 - Data/Access/SearchDAO.cs | 228 ++- Data/Entities/ConfirmationReceiptSignature.cs | 55 +- .../ConfirmationReceiptSignature.hbm.xml | 10 +- ...atureType_ConfirmationReceiptSignature.txt | 1 + ...merOid zu ConfirmationReceiptSignature.txt | 3 + .../Quittierungsbeleg.Designer.cs | 61 +- Report/DefaultReports/Quittierungsbeleg.cs | 58 +- Report/ReportObjects/ServicesOverviewRO.cs | 23 + ...ignatureDC_ConfirmationReceiptSignature.cs | 24 +- Service/OwnChat/OwnChatHelper.cs | 4 - Service/ServiceContracts/IEmployeeService.cs | 4 + .../ServiceContracts/IOperationsService.cs | 36 +- .../EmployeeServiceImp.cs | 93 +- .../OperationsServiceImp.cs | 139 +- Shared/BeWoEntityEnums.cs | 5 + .../ClientPartials/CostRatePeriodDC.cs | 14 +- .../ClientPartials/CompactOrganisationDC.cs | 4 +- .../ConfirmationReceiptSignatureDC.cs | 14 +- Shared/DataContracts/ContactDC.cs | 2 +- Shared/DataContracts/ServiceRecordDC.cs | 2 +- Shared/Shared.csproj | 1 + 37 files changed, 1415 insertions(+), 1957 deletions(-) delete mode 100644 BeWoPlanerMobil/Scripts/modernizr-2.8.3.js create mode 100644 Model/Changes_2021_01_20_SignatureType_ConfirmationReceiptSignature.txt create mode 100644 Model/Changes_2021_02_02_CustomerOid zu ConfirmationReceiptSignature.txt diff --git a/BeWo/ServiceProxy/Generated.cs b/BeWo/ServiceProxy/Generated.cs index 796f49a4d..122b0f59a 100644 --- a/BeWo/ServiceProxy/Generated.cs +++ b/BeWo/ServiceProxy/Generated.cs @@ -314,6 +314,10 @@ namespace BeWo.ServiceProxy "ault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BeWo.Service.ServiceContracts")] System.Collections.Generic.List GetActiveSupportConceptsForEmployee(System.Nullable employeeOid, BeWo.View.Navigation.Filter.CustomerFilterEnum supportConceptFilter); + [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IEmployeeService/FindTeamCustomers", ReplyAction="http://tempuri.org/IEmployeeService/FindTeamCustomersResponse")] + [System.ServiceModel.FaultContractAttribute(typeof(BeWo.ServiceProxy.BeWoFault), Action="http://tempuri.org/IEmployeeService/FindTeamCustomersBeWoFaultFault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BeWo.Service.ServiceContracts")] + System.Collections.Generic.List FindTeamCustomers(System.Nullable teamOid); + [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IEmployeeService/ArchiveEmployee", ReplyAction="http://tempuri.org/IEmployeeService/ArchiveEmployeeResponse")] [System.ServiceModel.FaultContractAttribute(typeof(BeWo.ServiceProxy.BeWoFault), Action="http://tempuri.org/IEmployeeService/ArchiveEmployeeBeWoFaultFault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BeWo.Service.ServiceContracts")] void ArchiveEmployee(long pOid, long pVersion); @@ -790,6 +794,11 @@ namespace BeWo.ServiceProxy return base.Channel.GetActiveSupportConceptsForEmployee(employeeOid, supportConceptFilter); } + public System.Collections.Generic.List FindTeamCustomers(System.Nullable teamOid) + { + return base.Channel.FindTeamCustomers(teamOid); + } + public void ArchiveEmployee(long pOid, long pVersion) { base.Channel.ArchiveEmployee(pOid, pVersion); @@ -1571,7 +1580,28 @@ namespace BeWo.ServiceProxy [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.List))] [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.DataContracts.Employee2SchedulerAppointmentDC))] [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary>))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.List))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.List>))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary>))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary>))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary>))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.SignatureType))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.HomeViewPanelType))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.Auszahlungsintervall))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.Zahlungstyp))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.VertretungsStatus))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.SchulbegleitenderZugehoerigkeitsTyp))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.MessageType))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.StatementType))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.ServiceRecordValidationResult))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.List))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.UiElementType))] [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.DataContracts.FlexibleReportFilterDC))] [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.List))] [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.DataContracts.FlexibleReportResultDC))] @@ -1676,26 +1706,7 @@ namespace BeWo.ServiceProxy [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.DataContracts.FLSAnalysisDataDetailDC))] [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.List))] [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.DataContracts.ServiceRecordFLSOverviewDC))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.HomeViewPanelType))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.Auszahlungsintervall))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.Zahlungstyp))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.VertretungsStatus))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.SchulbegleitenderZugehoerigkeitsTyp))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.MessageType))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.StatementType))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.ServiceRecordValidationResult))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.List))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.UiElementType))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.List>))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary>))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary))] - [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.Dictionary>))] + [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.List))] [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.DataContracts.Reports.AuslastungAnalysisRootDC))] [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.Generic.List))] [System.ServiceModel.ServiceKnownTypeAttribute(typeof(BS.Shared.DataContracts.Reports.AuslastungAnalysisEmployeeDC))] @@ -4809,6 +4820,20 @@ namespace BeWo.ServiceProxy public interface IOperationsService { + [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IOperationsService/LoadServiceRecordOidsWithCustomerConfirmati" + + "onReceiptSignatures", ReplyAction="http://tempuri.org/IOperationsService/LoadServiceRecordOidsWithCustomerConfirmati" + + "onReceiptSignaturesResponse")] + [System.ServiceModel.FaultContractAttribute(typeof(BeWo.ServiceProxy.BeWoFault), Action="http://tempuri.org/IOperationsService/LoadServiceRecordOidsWithCustomerConfirmati" + + "onReceiptSignaturesBeWoFaultFault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BeWo.Service.ServiceContracts")] + System.Collections.Generic.List LoadServiceRecordOidsWithCustomerConfirmationReceiptSignatures(System.Collections.Generic.List serviceRecordOids, BS.Shared.SignatureType signatureType); + + [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IOperationsService/GetServiceRecordsWithoutConfirmationReceipt" + + "Signature", ReplyAction="http://tempuri.org/IOperationsService/GetServiceRecordsWithoutConfirmationReceipt" + + "SignatureResponse")] + [System.ServiceModel.FaultContractAttribute(typeof(BeWo.ServiceProxy.BeWoFault), Action="http://tempuri.org/IOperationsService/GetServiceRecordsWithoutConfirmationReceipt" + + "SignatureBeWoFaultFault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BeWo.Service.ServiceContracts")] + System.Collections.Generic.List GetServiceRecordsWithoutConfirmationReceiptSignature(System.Collections.Generic.List serviceRecordOids, BS.Shared.SignatureType signatureType); + [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IOperationsService/GetFlexibleReportResult", ReplyAction="http://tempuri.org/IOperationsService/GetFlexibleReportResultResponse")] [System.ServiceModel.FaultContractAttribute(typeof(BeWo.ServiceProxy.BeWoFault), Action="http://tempuri.org/IOperationsService/GetFlexibleReportResultBeWoFaultFault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BeWo.Service.ServiceContracts")] BS.Shared.DataContracts.FlexibleReportResultDC GetFlexibleReportResult(BS.Shared.DataContracts.FlexibleReportFilterDC filter); @@ -4996,7 +5021,7 @@ namespace BeWo.ServiceProxy "tomerResponse")] [System.ServiceModel.FaultContractAttribute(typeof(BeWo.ServiceProxy.BeWoFault), Action="http://tempuri.org/IOperationsService/HasConfirmationReceiptSignatureByDateAndCus" + "tomerBeWoFaultFault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BeWo.Service.ServiceContracts")] - bool HasConfirmationReceiptSignatureByDateAndCustomer(long customerOid, BS.Shared.Core.DateTimeSpan timeSpan); + bool HasConfirmationReceiptSignatureByDateAndCustomer(long customerOid, BS.Shared.Core.DateTimeSpan timeSpan, BS.Shared.SignatureType signatureType); [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IOperationsService/LoadServiceCategory", ReplyAction="http://tempuri.org/IOperationsService/LoadServiceCategoryResponse")] [System.ServiceModel.FaultContractAttribute(typeof(BeWo.ServiceProxy.BeWoFault), Action="http://tempuri.org/IOperationsService/LoadServiceCategoryBeWoFaultFault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BeWo.Service.ServiceContracts")] @@ -5053,7 +5078,7 @@ namespace BeWo.ServiceProxy [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IOperationsService/HasConfirmationReceiptSignature", ReplyAction="http://tempuri.org/IOperationsService/HasConfirmationReceiptSignatureResponse")] [System.ServiceModel.FaultContractAttribute(typeof(BeWo.ServiceProxy.BeWoFault), Action="http://tempuri.org/IOperationsService/HasConfirmationReceiptSignatureBeWoFaultFau" + "lt", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BeWo.Service.ServiceContracts")] - bool HasConfirmationReceiptSignature(System.Collections.Generic.List customerOids, System.Nullable employeeOid, System.Nullable costbearerOid, System.Nullable serviceCategoryOid, BS.Shared.Core.DateTimeSpan timeSpan); + bool HasConfirmationReceiptSignature(System.Collections.Generic.List serviceRecordOids, BS.Shared.SignatureType signatureType); [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IOperationsService/ReplacePlaceholdersInTemplate", ReplyAction="http://tempuri.org/IOperationsService/ReplacePlaceholdersInTemplateResponse")] [System.ServiceModel.FaultContractAttribute(typeof(BeWo.ServiceProxy.BeWoFault), Action="http://tempuri.org/IOperationsService/ReplacePlaceholdersInTemplateBeWoFaultFault" + @@ -5072,6 +5097,46 @@ namespace BeWo.ServiceProxy [System.ServiceModel.FaultContractAttribute(typeof(BeWo.ServiceProxy.BeWoFault), Action="http://tempuri.org/IOperationsService/GetObjectForFilePathBeWoFaultFault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BeWo.Service.ServiceContracts")] string GetObjectForFilePath(BS.Shared.TableID table, System.Nullable oid); + [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IOperationsService/LoadConfirmationReceiptSignaturesByServiceR" + + "ecordOids", ReplyAction="http://tempuri.org/IOperationsService/LoadConfirmationReceiptSignaturesByServiceR" + + "ecordOidsResponse")] + [System.ServiceModel.FaultContractAttribute(typeof(BeWo.ServiceProxy.BeWoFault), Action="http://tempuri.org/IOperationsService/LoadConfirmationReceiptSignaturesByServiceR" + + "ecordOidsBeWoFaultFault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BeWo.Service.ServiceContracts")] + System.Collections.Generic.List LoadConfirmationReceiptSignaturesByServiceRecordOids(out System.Collections.Generic.List serviceRecordOidsWithSignatures, System.Collections.Generic.List serviceRecordOids, BS.Shared.SignatureType signatureType); + + [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IOperationsService/UpdateConfirmationReceiptSignatures", ReplyAction="http://tempuri.org/IOperationsService/UpdateConfirmationReceiptSignaturesResponse" + + "")] + [System.ServiceModel.FaultContractAttribute(typeof(BeWo.ServiceProxy.BeWoFault), Action="http://tempuri.org/IOperationsService/UpdateConfirmationReceiptSignaturesBeWoFaul" + + "tFault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BeWo.Service.ServiceContracts")] + System.Collections.Generic.List UpdateConfirmationReceiptSignatures(System.Collections.Generic.List confirmationReceiptSignatures2Update); + + [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IOperationsService/DeleteConfirmationReceiptSignatures", ReplyAction="http://tempuri.org/IOperationsService/DeleteConfirmationReceiptSignaturesResponse" + + "")] + [System.ServiceModel.FaultContractAttribute(typeof(BeWo.ServiceProxy.BeWoFault), Action="http://tempuri.org/IOperationsService/DeleteConfirmationReceiptSignaturesBeWoFaul" + + "tFault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BeWo.Service.ServiceContracts")] + void DeleteConfirmationReceiptSignatures(System.Collections.Generic.Dictionary oid2Version); + + [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IOperationsService/HasConfirmationReceiptSignaturesByCustomerA" + + "ndServiceRecords", ReplyAction="http://tempuri.org/IOperationsService/HasConfirmationReceiptSignaturesByCustomerA" + + "ndServiceRecordsResponse")] + [System.ServiceModel.FaultContractAttribute(typeof(BeWo.ServiceProxy.BeWoFault), Action="http://tempuri.org/IOperationsService/HasConfirmationReceiptSignaturesByCustomerA" + + "ndServiceRecordsBeWoFaultFault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BeWo.Service.ServiceContracts")] + bool HasConfirmationReceiptSignaturesByCustomerAndServiceRecords(long customerOid, System.Collections.Generic.List serviceRecordOids); + + [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IOperationsService/LoadAllConfirmationReceiptSignaturesByServi" + + "ceRecordOids", ReplyAction="http://tempuri.org/IOperationsService/LoadAllConfirmationReceiptSignaturesByServi" + + "ceRecordOidsResponse")] + [System.ServiceModel.FaultContractAttribute(typeof(BeWo.ServiceProxy.BeWoFault), Action="http://tempuri.org/IOperationsService/LoadAllConfirmationReceiptSignaturesByServi" + + "ceRecordOidsBeWoFaultFault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BeWo.Service.ServiceContracts")] + System.Collections.Generic.List LoadAllConfirmationReceiptSignaturesByServiceRecordOids(out System.Collections.Generic.Dictionary> serviceRecordOidsWithSignature, System.Collections.Generic.List serviceRecordOids); + + [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IOperationsService/LoadServiceRecordOidsWithConfirmationReceip" + + "tSignatures", ReplyAction="http://tempuri.org/IOperationsService/LoadServiceRecordOidsWithConfirmationReceip" + + "tSignaturesResponse")] + [System.ServiceModel.FaultContractAttribute(typeof(BeWo.ServiceProxy.BeWoFault), Action="http://tempuri.org/IOperationsService/LoadServiceRecordOidsWithConfirmationReceip" + + "tSignaturesBeWoFaultFault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BeWo.Service.ServiceContracts")] + System.Collections.Generic.List LoadServiceRecordOidsWithConfirmationReceiptSignatures(System.Collections.Generic.List serviceRecordOids); + [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IOperationsService/UpdateIsChatActiveCustomerAPPCodeDC", ReplyAction="http://tempuri.org/IOperationsService/UpdateIsChatActiveCustomerAPPCodeDCResponse" + "")] [System.ServiceModel.FaultContractAttribute(typeof(BeWo.ServiceProxy.BeWoFault), Action="http://tempuri.org/IOperationsService/UpdateIsChatActiveCustomerAPPCodeDCBeWoFaul" + @@ -5972,6 +6037,16 @@ namespace BeWo.ServiceProxy { } + public System.Collections.Generic.List LoadServiceRecordOidsWithCustomerConfirmationReceiptSignatures(System.Collections.Generic.List serviceRecordOids, BS.Shared.SignatureType signatureType) + { + return base.Channel.LoadServiceRecordOidsWithCustomerConfirmationReceiptSignatures(serviceRecordOids, signatureType); + } + + public System.Collections.Generic.List GetServiceRecordsWithoutConfirmationReceiptSignature(System.Collections.Generic.List serviceRecordOids, BS.Shared.SignatureType signatureType) + { + return base.Channel.GetServiceRecordsWithoutConfirmationReceiptSignature(serviceRecordOids, signatureType); + } + public BS.Shared.DataContracts.FlexibleReportResultDC GetFlexibleReportResult(BS.Shared.DataContracts.FlexibleReportFilterDC filter) { return base.Channel.GetFlexibleReportResult(filter); @@ -6172,9 +6247,9 @@ namespace BeWo.ServiceProxy return base.Channel.HasConfirmationReceiptSignaturesByEmployeeAndServiceRecords(employeeOid, serviceRecordOids); } - public bool HasConfirmationReceiptSignatureByDateAndCustomer(long customerOid, BS.Shared.Core.DateTimeSpan timeSpan) + public bool HasConfirmationReceiptSignatureByDateAndCustomer(long customerOid, BS.Shared.Core.DateTimeSpan timeSpan, BS.Shared.SignatureType signatureType) { - return base.Channel.HasConfirmationReceiptSignatureByDateAndCustomer(customerOid, timeSpan); + return base.Channel.HasConfirmationReceiptSignatureByDateAndCustomer(customerOid, timeSpan, signatureType); } public BS.Shared.DataContracts.ServiceCategoryDC LoadServiceCategory(long serviceCategoryOid) @@ -6237,9 +6312,9 @@ namespace BeWo.ServiceProxy base.Channel.DeleteTemplates(vorlagen); } - public bool HasConfirmationReceiptSignature(System.Collections.Generic.List customerOids, System.Nullable employeeOid, System.Nullable costbearerOid, System.Nullable serviceCategoryOid, BS.Shared.Core.DateTimeSpan timeSpan) + public bool HasConfirmationReceiptSignature(System.Collections.Generic.List serviceRecordOids, BS.Shared.SignatureType signatureType) { - return base.Channel.HasConfirmationReceiptSignature(customerOids, employeeOid, costbearerOid, serviceCategoryOid, timeSpan); + return base.Channel.HasConfirmationReceiptSignature(serviceRecordOids, signatureType); } public string ReplacePlaceholdersInTemplate(BS.Shared.DataContracts.DokumentvorlageDC template, System.Nullable objectOid, System.Nullable tableOid) @@ -6262,6 +6337,36 @@ namespace BeWo.ServiceProxy return base.Channel.GetObjectForFilePath(table, oid); } + public System.Collections.Generic.List LoadConfirmationReceiptSignaturesByServiceRecordOids(out System.Collections.Generic.List serviceRecordOidsWithSignatures, System.Collections.Generic.List serviceRecordOids, BS.Shared.SignatureType signatureType) + { + return base.Channel.LoadConfirmationReceiptSignaturesByServiceRecordOids(out serviceRecordOidsWithSignatures, serviceRecordOids, signatureType); + } + + public System.Collections.Generic.List UpdateConfirmationReceiptSignatures(System.Collections.Generic.List confirmationReceiptSignatures2Update) + { + return base.Channel.UpdateConfirmationReceiptSignatures(confirmationReceiptSignatures2Update); + } + + public void DeleteConfirmationReceiptSignatures(System.Collections.Generic.Dictionary oid2Version) + { + base.Channel.DeleteConfirmationReceiptSignatures(oid2Version); + } + + public bool HasConfirmationReceiptSignaturesByCustomerAndServiceRecords(long customerOid, System.Collections.Generic.List serviceRecordOids) + { + return base.Channel.HasConfirmationReceiptSignaturesByCustomerAndServiceRecords(customerOid, serviceRecordOids); + } + + public System.Collections.Generic.List LoadAllConfirmationReceiptSignaturesByServiceRecordOids(out System.Collections.Generic.Dictionary> serviceRecordOidsWithSignature, System.Collections.Generic.List serviceRecordOids) + { + return base.Channel.LoadAllConfirmationReceiptSignaturesByServiceRecordOids(out serviceRecordOidsWithSignature, serviceRecordOids); + } + + public System.Collections.Generic.List LoadServiceRecordOidsWithConfirmationReceiptSignatures(System.Collections.Generic.List serviceRecordOids) + { + return base.Channel.LoadServiceRecordOidsWithConfirmationReceiptSignatures(serviceRecordOids); + } + public void UpdateIsChatActiveCustomerAPPCodeDC(long customerOid, int activeType) { base.Channel.UpdateIsChatActiveCustomerAPPCodeDC(customerOid, activeType); diff --git a/BeWoPlanerMobil/App_Start/BundleConfig.cs b/BeWoPlanerMobil/App_Start/BundleConfig.cs index d18cc2707..05df9f2e3 100644 --- a/BeWoPlanerMobil/App_Start/BundleConfig.cs +++ b/BeWoPlanerMobil/App_Start/BundleConfig.cs @@ -1,5 +1,4 @@ -using System.Web; -using System.Web.Optimization; +using System.Web.Optimization; namespace BeWoPlanerMobil { @@ -18,11 +17,6 @@ namespace BeWoPlanerMobil // "~/Scripts/jquery.unobtrusive*", // "~/Scripts/jquery.validate*")); - // Use the development version of Modernizr to develop with and learn from. Then, when you're - // ready for production, use the build tool at http://modernizr.com to pick only the tests you need. - bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( - "~/Scripts/modernizr-*")); - //bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css")); //bundles.Add(new StyleBundle("~/Content/themes/base/css").Include( diff --git a/BeWoPlanerMobil/BeWoPlanerMobil.csproj b/BeWoPlanerMobil/BeWoPlanerMobil.csproj index 5268c62bb..1fbea5d9e 100644 --- a/BeWoPlanerMobil/BeWoPlanerMobil.csproj +++ b/BeWoPlanerMobil/BeWoPlanerMobil.csproj @@ -89,6 +89,8 @@ False ..\Lib\NHibernate.dll + + ..\packages\RestSharp.106.10.1\lib\net452\RestSharp.dll @@ -312,7 +314,6 @@ - diff --git a/BeWoPlanerMobil/Controllers/MainController.cs b/BeWoPlanerMobil/Controllers/MainController.cs index 38afdce54..88a75cde2 100644 --- a/BeWoPlanerMobil/Controllers/MainController.cs +++ b/BeWoPlanerMobil/Controllers/MainController.cs @@ -214,7 +214,7 @@ namespace BeWoPlanerMobil.Controllers } var endtime = GetSettingValue(mandator.Settings, "IsEndDateVisible"); - + Model.IsEndDateVisible = Equals(endtime, "1"); var isDurationMinHoursSwitchableSetting = GetSettingValue(mandator.Settings, "IsZeiterfassungInStdMin"); @@ -504,21 +504,20 @@ namespace BeWoPlanerMobil.Controllers } } - private void ApplyWatermark() + public static string ApplyWatermark(string blob, string watermarkImagePath) { - if (Model == null || string.IsNullOrWhiteSpace(Model.SignatureImage)) + if(string.IsNullOrWhiteSpace(blob)) { - Logout(); - return; + return null; } - var watermarkImage = Image.FromFile(Server.MapPath("../Content/images/bewoplaner_logo_big.png")); + var watermarkImage = Image.FromFile(watermarkImagePath); - var signatureImage = SignatureUtils.Base64StringToBitmap(Model.SignatureImage); + var signatureImage = SignatureUtils.Base64StringToBitmap(blob); - var hasTransparentBackground = SignatureUtils.HasTransparentBackground(Model.SignatureImage); + var hasTransparentBackground = SignatureUtils.HasTransparentBackground(blob); - if (hasTransparentBackground) + if(hasTransparentBackground) { signatureImage = SignatureUtils.AddBackgroundToBitmap(signatureImage, Color.White); } @@ -527,7 +526,7 @@ namespace BeWoPlanerMobil.Controllers for(var y = 0; y < signatureImage.Height; y++) { - for (var x = 0; x < signatureImage.Width; x++) + for(var x = 0; x < signatureImage.Width; x++) { watermarker.Position = WatermarkPosition.Absolute; watermarker.PositionX = x; @@ -543,7 +542,7 @@ namespace BeWoPlanerMobil.Controllers y += watermarkImage.Height; } - Model.SignatureImage = "data:image/png;base64," + SignatureUtils.ConvertImageToBase64String(watermarker.Image); + return "data:image/png;base64," + SignatureUtils.ConvertImageToBase64String(watermarker.Image); } [Authorize] @@ -728,6 +727,12 @@ namespace BeWoPlanerMobil.Controllers var enddatum = datum; + var endDateString = collection[FormCollectionConstants.EndDateKey]; + if(endDateString != null) + { + enddatum = Convert.ToDateTime(endDateString); + } + var start = collection[FormCollectionConstants.StartKey]; var ende = collection[FormCollectionConstants.EndKey]; var dauer = 0; @@ -1614,13 +1619,18 @@ namespace BeWoPlanerMobil.Controllers var startHoursDt = ConvertTimeStringToDateTime(startString); var endHoursDt = ConvertTimeStringToDateTime(endString); - if (!DateTime.TryParse(dateString, out var date)) + if(!DateTime.TryParse(von, out var startDate)) { - date = DateTime.Now.Date; + startDate = DateTime.Now.Date; } - var startDt = date.AddHours(startHoursDt.Hour).AddMinutes(startHoursDt.Minute); - var endDt = date.AddHours(endHoursDt.Hour).AddMinutes(endHoursDt.Minute); + if(!DateTime.TryParse(bis, out var endDate)) + { + endDate = DateTime.Now.Date; + } + + var startDt = startDate.AddHours(startHoursDt.Hour).AddMinutes(startHoursDt.Minute); + var endDt = endDate.AddHours(endHoursDt.Hour).AddMinutes(endHoursDt.Minute); if (startDt > endDt) { @@ -2351,6 +2361,7 @@ namespace BeWoPlanerMobil.Controllers var isParsingSuccessful2 = long.TryParse(pFormCollection[FormCollectionConstants.ServiceRecordOidHolder2Key], out var serviceRecordOid); var isParsingSuccessful = long.TryParse(pFormCollection[FormCollectionConstants.SignatureOidHolderKey], out var signatureOid); + if(isParsingSuccessful && isParsingSuccessful2) { var signatureServiceRecord = Model.ServiceRecords.FirstOrDefault(serviceRecord => serviceRecord.ServiceRecordOid.Equals(serviceRecordOid)); @@ -2359,7 +2370,7 @@ namespace BeWoPlanerMobil.Controllers Model.SignatureImage = OperationsService.GetSignature(signatureOid).DataBild; - ApplyWatermark(); + Model.SignatureImage = ApplyWatermark(Model.SignatureImage, Server.MapPath("../Content/images/bewoplaner_logo_big.png")); } return RedirectToActionPermanent("Main"); @@ -2585,8 +2596,6 @@ namespace BeWoPlanerMobil.Controllers if(Model.IsInGroupBookingMode && Model.SelectedSupportConcepts.Count > 1) { -// ResetGroupBookingMode(true); - return SaveGroupBooking(); } @@ -2604,6 +2613,7 @@ namespace BeWoPlanerMobil.Controllers return ResetEditingMode(); } + // Wird zum Bearbeiten von Gruppenbuchungen benutzt [HttpPost] [Authorize] public ActionResult EditServiceRecord(FormCollection formCollection) diff --git a/BeWoPlanerMobil/Controllers/ReportController.cs b/BeWoPlanerMobil/Controllers/ReportController.cs index 3ced98cda..715a761c2 100644 --- a/BeWoPlanerMobil/Controllers/ReportController.cs +++ b/BeWoPlanerMobil/Controllers/ReportController.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Web.Mvc; -using BeWo.Report; +using BeWo.Report; using BeWo.Report.ReportObjects; using BeWoPlanerMobil.Models; using BeWoPlanerMobil.Service; @@ -13,29 +8,14 @@ using BS.Shared; using BS.Shared.Core; using BS.Shared.DataContracts; using BS.Shared.Extensions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web.Mvc; namespace BeWoPlanerMobil.Controllers { - /* - * Quittierungsbeleg wie im Fat-Client implementieren ✓ - * Mit Unterschriftenfunktion für den Mitarbeiter ✓ - * Liste mit allen ServiceRecords des Mitarbeiters für einen Klienten ✓ - * - * TODO: Beim Speichern von ServiceRecords prüfen, ob es schon eine Mitarbeiterunterschrift für Quittierungsbelege gibt ✓ - * TODO: Unterschrift in Quittierungsbeleg einbauen - * TODO: Bei neuer Unterschrift für einen Zeitraum die alte löschen - - * TODO: - * TODO: Flag wie ShowSignature, genannt ShowEmployeeSignature - * TODO: ServiceRecords eines Quittierungsbelegs müssen mit einer Mitarbeiterunterschrift verknüpft sein, damit die Unterschrift angezeigt wird. - * TODO: - * TODO: Rechte: - * TODO: - * TODO: Für das Standartdatum den ersten des letzten Monats nehmen ✓ - * - * - */ - public class ReportController : AbstractBaseController { private ReportModel _Model; @@ -77,7 +57,7 @@ namespace BeWoPlanerMobil.Controllers return RedirectToActionPermanent("Main", "Main"); } - // Damit das Standartdatum beim allerersten Aufruf gesetzt werden kann, gibt es die InitReports-Methode + CreateServiceOverview(null); return View(Model); } @@ -101,10 +81,10 @@ namespace BeWoPlanerMobil.Controllers var first = new DateTime(year, month, 1).AddMonths(-1); var last = first.AddMonths(1).AddDays(-1); - Model.SelectedYear = first.Year; - Model.SelectedMonth = first.Month; + Model.SelectedYear = first.Year; + Model.SelectedMonth = first.Month; Model.SelectedStartDay = first.Day; - Model.SelectedEndDay = last.Day; + Model.SelectedEndDay = last.Day; var filterEnums = Enum.GetValues(typeof(QBFilterEnum)).Cast(); @@ -137,9 +117,14 @@ namespace BeWoPlanerMobil.Controllers return Logout(); } + if(Model.SelectedFilterItem == null) + { + return RedirectToActionPermanent("Report"); + } + if(Model.SelectedFilterItem.FilterEnum == QBFilterEnum.KlientenAuswahl) { - var customerOidString = formCollection[FormCollectionConstants.SelectedCustomerOidKey]; + var customerOidString = formCollection == null ? Model.SelectedCustomerOid.ToString() : formCollection[FormCollectionConstants.SelectedCustomerOidKey]; var isCustomerOidSuccessful = long.TryParse(customerOidString, out var selectedCustomerOid); @@ -157,7 +142,7 @@ namespace BeWoPlanerMobil.Controllers if(Model.SelectedFilterItem.FilterEnum == QBFilterEnum.TeamAuswahl) { - var teamOidString = formCollection[FormCollectionConstants.SelectedTeamOidKey]; + var teamOidString = formCollection == null ? Model.SelectedTeamOid.ToString() : formCollection[FormCollectionConstants.SelectedTeamOidKey]; var isTeamOidSuccessful = long.TryParse(teamOidString, out var selectedTeamOid); @@ -179,13 +164,13 @@ namespace BeWoPlanerMobil.Controllers var reportObjects = new List(); var month = Model.SelectedMonth; - var year = Model.SelectedYear; + var year = Model.SelectedYear; - var organisationOid = Model.SelectedOrganisationOid ?? 0; - var employeeOid = Model.SelectedEmployeeOid ?? 0; + var organisationOid = Model.SelectedOrganisationOid ?? 0; + var employeeOid = Model.SelectedEmployeeOid ?? 0; var serviceCategoryOid = Model.SelectedServiceCategoryOid; - var teamOid = Model.SelectedTeamOid; - var customerOid = Model.SelectedCustomerOid ?? 0; + var teamOid = Model.SelectedTeamOid; + var customerOid = Model.SelectedCustomerOid ?? 0; switch(Model.SelectedFilterItem.FilterEnum) { @@ -211,20 +196,63 @@ namespace BeWoPlanerMobil.Controllers reportObjects = ServicesOverviewRO.Create(month, year, organisationOid, employeeOid, startDay, endDay, serviceCategoryOid, true, false); break; } + + reportObjects = reportObjects.Where(x => x != null).ToList(); + + var srOids = new List(); + + reportObjects.DoForEach(x => x.Services.DoForEach(s => srOids.AddIfNotIn(s.ServiceRecordOid))); + + Model.ConfirmationReceiptSignatures = OperationsService.LoadAllConfirmationReceiptSignaturesByServiceRecordOids(srOids, out var serviceRecordOidsWithSignature); + + var customerSignatures = Model.ConfirmationReceiptSignatures.Where(crs => crs.SignatureType == SignatureType.Customer); + var employeeSignatures = Model.ConfirmationReceiptSignatures.Where(crs => crs.SignatureType == SignatureType.Employee); + + Model.ReportServiceRecordOids = new List(); + reportObjects.DoForEach(ro => ro.Services.DoForEach(s => + { + Model.ReportServiceRecordOids.AddIfNotIn(s.ServiceRecordOid); + })); + + var hasEmployeeSignature = srOids.All(a => serviceRecordOidsWithSignature.ContainsKey(SignatureType.Employee) && serviceRecordOidsWithSignature[SignatureType.Employee].Contains(a)); Model.ConfirmationReceiptObject = null; - Model.ConfirmationReceiptObject = new ConfirmationReceiptObject(BuildInformationString(), new List()); + Model.ConfirmationReceiptObject = new ConfirmationReceiptObject(BuildInformationString(), new List(), BuildInformationString(true), GetTimeSpanString(), hasEmployeeSignature, employeeSignatures.ToList()); - reportObjects.DoForEach(ro => + reportObjects.DoForEach(reportObject => { var quittierungsbelegItems = new List(); - ro.Services.DoForEach(serviceDetail => { quittierungsbelegItems.Add(new QuittierungsbelegItem(serviceDetail)); }); + reportObject.Services.DoForEach(serviceDetail => + { + quittierungsbelegItems.Add(new QuittierungsbelegItem(serviceDetail)); + }); - Model.ConfirmationReceiptObject.ConfirmationReceiptResultList.Add(new QuittierungsbelegResult(ro.CustomerName, quittierungsbelegItems)); + if(quittierungsbelegItems.Count == 0) + { + return; + } + + var oids = quittierungsbelegItems.Select(s => s.ServiceRecordOid); + + var hasCustomerSignature = oids.All(a => serviceRecordOidsWithSignature.ContainsKey(SignatureType.Customer) && serviceRecordOidsWithSignature[SignatureType.Customer].Contains(a)); + + var customerSignatureOid = hasCustomerSignature ? customerSignatures.FirstOrDefault(cs => cs.ServiceRecords.All(a => a.Customer.CustomerOid.Equals(reportObject.CustomerOid) && a.ServiceRecordOid.HasValue && serviceRecordOidsWithSignature[SignatureType.Customer].Contains(a.ServiceRecordOid.Value)))?.ConfirmationReceiptSignatureOid : null; + + Model.ConfirmationReceiptObject.ConfirmationReceiptResultList.Add( + new QuittierungsbelegResult + ( + $"{reportObject.CustomerLastName}, " + + $"{reportObject.CustomerFirstName}", + quittierungsbelegItems, + reportObject.CustomerOid, + hasCustomerSignature, + customerSignatureOid + ) + ); }); - if(Model.ConfirmationReceiptObject.ConfirmationReceiptResultList.Count == 0) + if(Model.ConfirmationReceiptObject.ConfirmationReceiptResultList.All(qbItem => qbItem.Items.Count == 0)) { TempData["HasWarningMessage"] = true; } @@ -232,28 +260,33 @@ namespace BeWoPlanerMobil.Controllers return RedirectToActionPermanent("Report"); } - private string BuildInformationString() + private string BuildInformationString(bool isDativ = false) { - var stringBuilder = new StringBuilder("Einträge für "); + var stringBuilder = new StringBuilder(isDativ ? string.Empty : "Einträge für "); - //Einträge für [alle Klienten/die Klienten meines Teams/meine Klienten/[CustomerName]/[TeamName]] [von [Mitarbeiter] [bei [Kostenträger]] und [Leistungskategorie]] vom 01.10. bis 31.10.2020 + // Einträge für [alle Klienten/die Klienten meines Teams/meine Klienten/[CustomerName]/[TeamName]] [von [Mitarbeiter] [bei [Kostenträger]] und [Leistungskategorie]] vom 01.10. bis 31.10.2020 // Einträge für Grube, Clair von Fisher, George bei LWL und face-to-face vom 01.10. bis 31.10.2020 + // Unterschrift für x erbrachte Leistungen von + switch(Model.SelectedFilterItem.FilterEnum) { case QBFilterEnum.KlientenAuswahl: stringBuilder.Append(Model.SelectedCustomer); break; case QBFilterEnum.MeineKlienten: - stringBuilder.Append("meine Klienten"); + stringBuilder.Append(isDativ ? "meinen" : "meine"); + stringBuilder.Append(" Klienten"); break; case QBFilterEnum.NurKlientenMeinesTeams: - stringBuilder.Append("die Klienten meines Teams"); + stringBuilder.Append(isDativ ? "den" : "die"); + stringBuilder.Append(" Klienten meines Teams"); break; case QBFilterEnum.TeamAuswahl: stringBuilder.Append(Model.SelectedTeam); break; default: - stringBuilder.Append("alle Klienten"); + stringBuilder.Append(isDativ ? "allen" : "alle"); + stringBuilder.Append(" Klienten"); break; } @@ -279,16 +312,21 @@ namespace BeWoPlanerMobil.Controllers stringBuilder.Append(Model.SelectedServiceCategory.Name); } - var month = Model.SelectedMonth < 10 ? $"0{Model.SelectedMonth}" : Model.SelectedMonth.ToString(); - var year = Model.SelectedYear; - var vom = Model.SelectedStartDay < 10 ? $"0{Model.SelectedStartDay}" : Model.SelectedStartDay.ToString(); - var bis = Model.SelectedEndDay < 10 ? $"0{Model.SelectedEndDay}" : Model.SelectedEndDay.ToString(); - - stringBuilder.Append($"vom {vom}.{month}. bis {bis}.{month}.{year}"); + stringBuilder.Append(GetTimeSpanString()); return stringBuilder.ToString(); } + private string GetTimeSpanString() + { + var month = Model.SelectedMonth < 10 ? $"0{Model.SelectedMonth}" : Model.SelectedMonth.ToString(); + var year = Model.SelectedYear; + var vom = Model.SelectedStartDay < 10 ? $"0{Model.SelectedStartDay}" : Model.SelectedStartDay.ToString(); + var bis = Model.SelectedEndDay < 10 ? $"0{Model.SelectedEndDay}" : Model.SelectedEndDay.ToString(); + + return $"vom {vom}.{month}. bis {bis}.{month}.{year}"; + } + private IEnumerable GetTeamCustomerOids(long? teamOid = null) { var customerOids = new List(); @@ -314,139 +352,6 @@ namespace BeWoPlanerMobil.Controllers return _LeerzeichenFuerGetMethoden; } - [Authorize] - [HttpPost] - public string CreateEmployeeSignatureForServiceOverview(string base64SignatureString) - { - if(Model == null) - { - Logout(); - } - - var confirmationReceiptSignature = new ConfirmationReceiptSignatureDC(); - - var serviceRecordOids = new List(); - - Model.ConfirmationReceiptObject.ConfirmationReceiptResultList.DoForEach(result => result.Items.DoForEach(item => serviceRecordOids.AddIfNotIn(item.ServiceRecordOid))); - - var serviceRecords = OperationsService.GetServiceRecordsByIds(serviceRecordOids); - - confirmationReceiptSignature.ServiceRecords = serviceRecords; - confirmationReceiptSignature.EmployeeOid = Model.Employee.EmployeeOid; - - // TODO: Prüfen, ob es bereits eine oder mehrere Mitarbeiterunterschriften gibt und die gegebenenfalls löschen - var signatureToDelete = OperationsService.FindConfirmationReceiptSignaturesByEmployeeAndServiceRecords(Model.Employee.EmployeeOid.Value, serviceRecordOids); - - using(var signatureBitmap = SignatureUtils.Base64StringToBitmap(base64SignatureString.Split(',')[1])) - { - var isValid = SignatureUtils.ValidateSignature(signatureBitmap); - - if(!isValid) - { - return MobileUtils.SerializeObject("Das Unterschriftenfeld darf nicht leer sein."); - } - - confirmationReceiptSignature.SignatureImage = base64SignatureString; - - OperationsService.InsertConfirmationReceiptSignature(confirmationReceiptSignature); - } - - return _LeerzeichenFuerGetMethoden; - } - - [Authorize] - public string ValidateEmployeeSignature() - { - if(Model?.Employee?.EmployeeOid == null) - { - Logout(); - return _LeerzeichenFuerGetMethoden; - } - - var serviceRecordOids = new List(); - - Model.ConfirmationReceiptObject.ConfirmationReceiptResultList.DoForEach(result => - { - result.Items.DoForEach(item => - { - serviceRecordOids.AddIfNotIn(item.ServiceRecordOid); - }); - }); - - var hasSignature = OperationsService.HasConfirmationReceiptSignaturesByEmployeeAndServiceRecords(Model.Employee.EmployeeOid.Value, serviceRecordOids); - - return hasSignature.ToString(); - } - - [Authorize] - public string CheckForEmployeeSignature(string customerOidString, string monthString, string yearString, string startDayString, string endDayString, string costbearerOidString, string employeeOidString, string serviceCategoryOidString) - { - if(Model?.Employee?.EmployeeOid == null) - { - Logout(); - } - - // TODO: Auswahl beachten - /* - * Methode im SearchDAO anpassen an Kostenträger, Leistungskategorie, Mitarbeiter, Team - */ - - var isParsingSuccessful1 = long.TryParse(customerOidString, out var customerOid); - var isParsingSuccessful2 = int.TryParse(monthString, out var month); - var isParsingSuccessful3 = int.TryParse(yearString, out var year); - var isParsingSuccessful4 = int.TryParse(startDayString, out var startDay); - var isParsingSuccessful5 = int.TryParse(endDayString, out var endDay); - - long.TryParse(costbearerOidString, out var organisationOid); - long.TryParse(employeeOidString, out var employeeOid); - long.TryParse(serviceCategoryOidString, out var serviceCategoryOid); - - var customerOids = new List(); - - if(Model.SelectedFilterItem != null) - { - switch(Model.SelectedFilterItem.FilterEnum) - { - case QBFilterEnum.AlleKlienten: - customerOids = EmployeeService.GetActiveCompactCustomersForEmployee(Model.Employee.EmployeeOid).Select(s => s.CustomerOid).ToList(); - break; - case QBFilterEnum.NurKlientenMeinesTeams: - customerOids = GetTeamCustomerOids().ToList(); - break; - case QBFilterEnum.MeineKlienten: - customerOids = DefaultReportCreator.GetMeineKlientenOids().ToList(); - break; - case QBFilterEnum.KlientenAuswahl: - customerOids = new List {customerOid}; - break; - case QBFilterEnum.TeamAuswahl: - break; - } - } - - long? costbearerOid = null; - if(organisationOid > 0) - { - var organisation = Model.Organisations.FirstOrDefault(o => o.OrganisationOid.Equals(organisationOid)); - costbearerOid = organisation?.CostBearerOid; - } - - //if(isParsingSuccessful1 && isParsingSuccessful2 && isParsingSuccessful3 && isParsingSuccessful4 && isParsingSuccessful5 && year > 0) - if(isParsingSuccessful2 && isParsingSuccessful3 && isParsingSuccessful4 && isParsingSuccessful5 && year > 0) - { - var theTimeSpan = new DateTimeSpan(new DateTime(year, month, startDay), new DateTime(year, month, endDay)); - - //var hasSignature = OperationsService.HasConfirmationReceiptSignatureByDateAndCustomer(customerOid, theTimeSpan); - - var test = OperationsService.HasConfirmationReceiptSignature(customerOids, employeeOid == 0 ? null : (long?) employeeOid, costbearerOid, serviceCategoryOid == 0 ? null : (long?) serviceCategoryOid, theTimeSpan); - - //return MobileUtils.SerializeObject(hasSignature); - return MobileUtils.SerializeObject(false); - } - - return _LeerzeichenFuerGetMethoden; - } - [Authorize] public string ChangeDateSelection(string startDayString, string endDayString, string monthString, string yearString) { @@ -469,8 +374,6 @@ namespace BeWoPlanerMobil.Controllers Model.SelectedStartDay = start.Day; Model.SelectedMonth = month; Model.SelectedYear = year; - - return MobileUtils.SerializeObject(true); } return _LeerzeichenFuerGetMethoden; @@ -517,5 +420,133 @@ namespace BeWoPlanerMobil.Controllers return _LeerzeichenFuerGetMethoden; } + + [Authorize] + [HttpPost] + public string CreateSignatureForServiceOverview(string base64SignatureString, string customerOidString, bool? isCustomerSignature, bool? overwrite) + { + if(Model == null) + { + Logout(); + return _LeerzeichenFuerGetMethoden; + } + + var shouldOverwrite = overwrite.HasValue && overwrite.Value; + + var customerOid = 0L; + + var isCustomerSig = isCustomerSignature.HasValue && isCustomerSignature.Value; + + if(isCustomerSig) + { + var isSuccessful = long.TryParse(customerOidString, out customerOid); + + if(!isSuccessful || customerOid == 0) + { + return MobileUtils.SerializeObject("Es ist ein unbekannter Fehler aufgetreten. Bitte wenden Sie sich an den Administrator."); + } + } + + var signatureType = isCustomerSig ? SignatureType.Customer : SignatureType.Employee; + + var serviceRecordOids = new List(); + + var resultList = Model.ConfirmationReceiptObject.ConfirmationReceiptResultList; + + if(isCustomerSig) + { + resultList = resultList.Where(item => item.CustomerOid == customerOid).ToList(); + } + + resultList.DoForEach(result => result.Items.DoForEach(item => serviceRecordOids.AddIfNotIn(item.ServiceRecordOid))); + + var existingServiceRecordSignatures = OperationsService.LoadConfirmationReceiptSignaturesByServiceRecordOids(serviceRecordOids, signatureType, out var serviceRecordOidsWithSignature); + + var serviceRecords = OperationsService.GetServiceRecordsByIds(serviceRecordOids); + + using(var signatureBitmap = SignatureUtils.Base64StringToBitmap(base64SignatureString.Split(',')[1])) + { + // TODO: TimeSpanString hinzufügen + /* + * 01.01. - 17.01.2021 -> werden wegen überschreiben ein paar Einträge entfernt, muss auch der String angepasst werden + * Das erste StartDate und das letzte EndDate können nicht im gewählten Monat liegen: 31.12.2020 22:00 bis 01.01.2021 03:00. + */ + var isValid = SignatureUtils.ValidateSignature(signatureBitmap); + + if(!isValid) + { + return MobileUtils.SerializeObject("Das Unterschriftenfeld darf nicht leer sein."); + } + + if(shouldOverwrite) + { + foreach(var csr in existingServiceRecordSignatures) + { + var temp = csr.ServiceRecords.Where(sr => sr.ServiceRecordOid.HasValue && !serviceRecordOidsWithSignature.Contains(sr.ServiceRecordOid.Value)); + csr.ServiceRecords.Clear(); + csr.ServiceRecords.AddRangeIfElementsNotIn(temp); + + if(csr.ServiceRecords.Count == 0 && csr.ConfirmationReceiptSignatureOid.HasValue) + { + OperationsService.DeleteConfirmationReceiptSignature(csr.ConfirmationReceiptSignatureOid.Value); + } + else + { + OperationsService.UpdateConfirmationReceiptSignature(csr); + } + } + } + else + { + serviceRecords = serviceRecords.Where(sr => sr.ServiceRecordOid.HasValue && !serviceRecordOidsWithSignature.Contains(sr.ServiceRecordOid.Value)).ToList(); + } + + var timeSpanString = GetTimeSpanString(); + if(timeSpanString.Contains("vom")) + { + timeSpanString = timeSpanString.Substring(4); + } + + var confirmationReceiptSignature = new ConfirmationReceiptSignatureDC + { + ServiceRecords = serviceRecords, + CustomerOid = isCustomerSig ? (long?) customerOid : null, + Employee = isCustomerSig ? null : MobileSessionFacade.LoggedInCompactEmployee, + SignatureImage = base64SignatureString, + SignatureType = signatureType, + TimeSpanString = timeSpanString + }; + + OperationsService.InsertConfirmationReceiptSignature(confirmationReceiptSignature); + } + + return _LeerzeichenFuerGetMethoden; + } + + [Authorize] + public string LoadConfirmationReceiptSignature(string signatureOidString) + { + try + { + if(Model == null) + { + Logout(); + return _LeerzeichenFuerGetMethoden; + } + + if(long.TryParse(signatureOidString, out var signatureOid)) + { + var signature = Model.GetConfirmationReceiptSignatureByOid(signatureOid); + + return signature?.SignatureImage != null ? MainController.ApplyWatermark(signature.SignatureImage, Server.MapPath("../Content/images/bewoplaner_logo_big.png")) : null; + } + + return _LeerzeichenFuerGetMethoden; + } + catch(Exception exception) + { + return MobileUtils.SerializeObject("Ein Fehler ist aufgetreten. Bitte wenden Sie sich an Ihren Administrator."); + } + } } } \ No newline at end of file diff --git a/BeWoPlanerMobil/Models/ReportModel.cs b/BeWoPlanerMobil/Models/ReportModel.cs index 452d5525c..cb47e26e9 100644 --- a/BeWoPlanerMobil/Models/ReportModel.cs +++ b/BeWoPlanerMobil/Models/ReportModel.cs @@ -238,5 +238,14 @@ namespace BeWoPlanerMobil.Models return result; } } + + public List ReportServiceRecordOids { get; set; } + + public List ConfirmationReceiptSignatures { get; set; } = new List(); + + public ConfirmationReceiptSignatureDC GetConfirmationReceiptSignatureByOid(long confirmationReceiptSignatureOid) + { + return ConfirmationReceiptSignatures.FirstOrDefault(crs => crs.ConfirmationReceiptSignatureOid == confirmationReceiptSignatureOid); + } } } \ No newline at end of file diff --git a/BeWoPlanerMobil/Scripts/mobileUtils.js b/BeWoPlanerMobil/Scripts/mobileUtils.js index 04014ce2d..7ad986a30 100644 --- a/BeWoPlanerMobil/Scripts/mobileUtils.js +++ b/BeWoPlanerMobil/Scripts/mobileUtils.js @@ -43,7 +43,8 @@ function showMessagePopupWithCallback(title, message, callback, executeCallbackB callback(); }); - if (executeCallbackByBothButtons === true) { + if(executeCallbackByBothButtons === true) { + $("#message-popup-close-btn, #message-popup-esc-btn").off("click"); $("#message-popup-close-btn, #message-popup-esc-btn").on("click", function() { callback(); @@ -168,11 +169,13 @@ function showAlertMessageBox(title, message, callback, executeCallbackByBothButt $("#popupMessage").text(message); + $("#message-popup-ok-btn").off("click"); $("#message-popup-ok-btn").on("click", function() { callback(); }); if(executeCallbackByBothButtons === true) { + $("#message-popup-close-btn").off("click"); $("#message-popup-close-btn").on("click", function() { callback(); }); @@ -193,14 +196,12 @@ function showWarningMessageBox(title, message, callback, executeCallbackByBothBu $("#popupMessage").text(message); - $("#message-popup-ok-btn").on("click", function() { - callback(); - }); + $("#message-popup-ok-btn").off("click"); + $("#message-popup-ok-btn").on("click", callback); if(executeCallbackByBothButtons === true) { - $("#message-popup-close-btn").on("click", function() { - callback(); - }); + $("#message-popup-close-btn").off("click"); + $("#message-popup-close-btn").on("click", callback); } $("#messagePopup").modal( diff --git a/BeWoPlanerMobil/Scripts/modernizr-2.8.3.js b/BeWoPlanerMobil/Scripts/modernizr-2.8.3.js deleted file mode 100644 index 33653390e..000000000 --- a/BeWoPlanerMobil/Scripts/modernizr-2.8.3.js +++ /dev/null @@ -1,1406 +0,0 @@ -/*! - * Modernizr v2.8.3 - * www.modernizr.com - * - * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton - * Available under the BSD and MIT licenses: www.modernizr.com/license/ - */ - -/* - * Modernizr tests which native CSS3 and HTML5 features are available in - * the current UA and makes the results available to you in two ways: - * as properties on a global Modernizr object, and as classes on the - * element. This information allows you to progressively enhance - * your pages with a granular level of control over the experience. - * - * Modernizr has an optional (not included) conditional resource loader - * called Modernizr.load(), based on Yepnope.js (yepnopejs.com). - * To get a build that includes Modernizr.load(), as well as choosing - * which tests to include, go to www.modernizr.com/download/ - * - * Authors Faruk Ates, Paul Irish, Alex Sexton - * Contributors Ryan Seddon, Ben Alman - */ - -window.Modernizr = (function( window, document, undefined ) { - - var version = '2.8.3', - - Modernizr = {}, - - /*>>cssclasses*/ - // option for enabling the HTML classes to be added - enableClasses = true, - /*>>cssclasses*/ - - docElement = document.documentElement, - - /** - * Create our "modernizr" element that we do most feature tests on. - */ - mod = 'modernizr', - modElem = document.createElement(mod), - mStyle = modElem.style, - - /** - * Create the input element for various Web Forms feature tests. - */ - inputElem /*>>inputelem*/ = document.createElement('input') /*>>inputelem*/ , - - /*>>smile*/ - smile = ':)', - /*>>smile*/ - - toString = {}.toString, - - // TODO :: make the prefixes more granular - /*>>prefixes*/ - // List of property values to set for css tests. See ticket #21 - prefixes = ' -webkit- -moz- -o- -ms- '.split(' '), - /*>>prefixes*/ - - /*>>domprefixes*/ - // Following spec is to expose vendor-specific style properties as: - // elem.style.WebkitBorderRadius - // and the following would be incorrect: - // elem.style.webkitBorderRadius - - // Webkit ghosts their properties in lowercase but Opera & Moz do not. - // Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+ - // erik.eae.net/archives/2008/03/10/21.48.10/ - - // More here: github.com/Modernizr/Modernizr/issues/issue/21 - omPrefixes = 'Webkit Moz O ms', - - cssomPrefixes = omPrefixes.split(' '), - - domPrefixes = omPrefixes.toLowerCase().split(' '), - /*>>domprefixes*/ - - /*>>ns*/ - ns = {'svg': 'http://www.w3.org/2000/svg'}, - /*>>ns*/ - - tests = {}, - inputs = {}, - attrs = {}, - - classes = [], - - slice = classes.slice, - - featureName, // used in testing loop - - - /*>>teststyles*/ - // Inject element with style element and some CSS rules - injectElementWithStyles = function( rule, callback, nodes, testnames ) { - - var style, ret, node, docOverflow, - div = document.createElement('div'), - // After page load injecting a fake body doesn't work so check if body exists - body = document.body, - // IE6 and 7 won't return offsetWidth or offsetHeight unless it's in the body element, so we fake it. - fakeBody = body || document.createElement('body'); - - if ( parseInt(nodes, 10) ) { - // In order not to give false positives we create a node for each test - // This also allows the method to scale for unspecified uses - while ( nodes-- ) { - node = document.createElement('div'); - node.id = testnames ? testnames[nodes] : mod + (nodes + 1); - div.appendChild(node); - } - } - - // '].join(''); - div.id = mod; - // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody. - // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270 - (body ? div : fakeBody).innerHTML += style; - fakeBody.appendChild(div); - if ( !body ) { - //avoid crashing IE8, if background image is used - fakeBody.style.background = ''; - //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible - fakeBody.style.overflow = 'hidden'; - docOverflow = docElement.style.overflow; - docElement.style.overflow = 'hidden'; - docElement.appendChild(fakeBody); - } - - ret = callback(div, rule); - // If this is done after page load we don't want to remove the body so check if body exists - if ( !body ) { - fakeBody.parentNode.removeChild(fakeBody); - docElement.style.overflow = docOverflow; - } else { - div.parentNode.removeChild(div); - } - - return !!ret; - - }, - /*>>teststyles*/ - - /*>>mq*/ - // adapted from matchMedia polyfill - // by Scott Jehl and Paul Irish - // gist.github.com/786768 - testMediaQuery = function( mq ) { - - var matchMedia = window.matchMedia || window.msMatchMedia; - if ( matchMedia ) { - return matchMedia(mq) && matchMedia(mq).matches || false; - } - - var bool; - - injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) { - bool = (window.getComputedStyle ? - getComputedStyle(node, null) : - node.currentStyle)['position'] == 'absolute'; - }); - - return bool; - - }, - /*>>mq*/ - - - /*>>hasevent*/ - // - // isEventSupported determines if a given element supports the given event - // kangax.github.com/iseventsupported/ - // - // The following results are known incorrects: - // Modernizr.hasEvent("webkitTransitionEnd", elem) // false negative - // Modernizr.hasEvent("textInput") // in Webkit. github.com/Modernizr/Modernizr/issues/333 - // ... - isEventSupported = (function() { - - var TAGNAMES = { - 'select': 'input', 'change': 'input', - 'submit': 'form', 'reset': 'form', - 'error': 'img', 'load': 'img', 'abort': 'img' - }; - - function isEventSupported( eventName, element ) { - - element = element || document.createElement(TAGNAMES[eventName] || 'div'); - eventName = 'on' + eventName; - - // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those - var isSupported = eventName in element; - - if ( !isSupported ) { - // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element - if ( !element.setAttribute ) { - element = document.createElement('div'); - } - if ( element.setAttribute && element.removeAttribute ) { - element.setAttribute(eventName, ''); - isSupported = is(element[eventName], 'function'); - - // If property was created, "remove it" (by setting value to `undefined`) - if ( !is(element[eventName], 'undefined') ) { - element[eventName] = undefined; - } - element.removeAttribute(eventName); - } - } - - element = null; - return isSupported; - } - return isEventSupported; - })(), - /*>>hasevent*/ - - // TODO :: Add flag for hasownprop ? didn't last time - - // hasOwnProperty shim by kangax needed for Safari 2.0 support - _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp; - - if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) { - hasOwnProp = function (object, property) { - return _hasOwnProperty.call(object, property); - }; - } - else { - hasOwnProp = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */ - return ((property in object) && is(object.constructor.prototype[property], 'undefined')); - }; - } - - // Adapted from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js - // es5.github.com/#x15.3.4.5 - - if (!Function.prototype.bind) { - Function.prototype.bind = function bind(that) { - - var target = this; - - if (typeof target != "function") { - throw new TypeError(); - } - - var args = slice.call(arguments, 1), - bound = function () { - - if (this instanceof bound) { - - var F = function(){}; - F.prototype = target.prototype; - var self = new F(); - - var result = target.apply( - self, - args.concat(slice.call(arguments)) - ); - if (Object(result) === result) { - return result; - } - return self; - - } else { - - return target.apply( - that, - args.concat(slice.call(arguments)) - ); - - } - - }; - - return bound; - }; - } - - /** - * setCss applies given styles to the Modernizr DOM node. - */ - function setCss( str ) { - mStyle.cssText = str; - } - - /** - * setCssAll extrapolates all vendor-specific css strings. - */ - function setCssAll( str1, str2 ) { - return setCss(prefixes.join(str1 + ';') + ( str2 || '' )); - } - - /** - * is returns a boolean for if typeof obj is exactly type. - */ - function is( obj, type ) { - return typeof obj === type; - } - - /** - * contains returns a boolean for if substr is found within str. - */ - function contains( str, substr ) { - return !!~('' + str).indexOf(substr); - } - - /*>>testprop*/ - - // testProps is a generic CSS / DOM property test. - - // In testing support for a given CSS property, it's legit to test: - // `elem.style[styleName] !== undefined` - // If the property is supported it will return an empty string, - // if unsupported it will return undefined. - - // We'll take advantage of this quick test and skip setting a style - // on our modernizr element, but instead just testing undefined vs - // empty string. - - // Because the testing of the CSS property names (with "-", as - // opposed to the camelCase DOM properties) is non-portable and - // non-standard but works in WebKit and IE (but not Gecko or Opera), - // we explicitly reject properties with dashes so that authors - // developing in WebKit or IE first don't end up with - // browser-specific content by accident. - - function testProps( props, prefixed ) { - for ( var i in props ) { - var prop = props[i]; - if ( !contains(prop, "-") && mStyle[prop] !== undefined ) { - return prefixed == 'pfx' ? prop : true; - } - } - return false; - } - /*>>testprop*/ - - // TODO :: add testDOMProps - /** - * testDOMProps is a generic DOM property test; if a browser supports - * a certain property, it won't return undefined for it. - */ - function testDOMProps( props, obj, elem ) { - for ( var i in props ) { - var item = obj[props[i]]; - if ( item !== undefined) { - - // return the property name as a string - if (elem === false) return props[i]; - - // let's bind a function - if (is(item, 'function')){ - // default to autobind unless override - return item.bind(elem || obj); - } - - // return the unbound function or obj or value - return item; - } - } - return false; - } - - /*>>testallprops*/ - /** - * testPropsAll tests a list of DOM properties we want to check against. - * We specify literally ALL possible (known and/or likely) properties on - * the element including the non-vendor prefixed one, for forward- - * compatibility. - */ - function testPropsAll( prop, prefixed, elem ) { - - var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), - props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); - - // did they call .prefixed('boxSizing') or are we just testing a prop? - if(is(prefixed, "string") || is(prefixed, "undefined")) { - return testProps(props, prefixed); - - // otherwise, they called .prefixed('requestAnimationFrame', window[, elem]) - } else { - props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); - return testDOMProps(props, prefixed, elem); - } - } - /*>>testallprops*/ - - - /** - * Tests - * ----- - */ - - // The *new* flexbox - // dev.w3.org/csswg/css3-flexbox - - tests['flexbox'] = function() { - return testPropsAll('flexWrap'); - }; - - // The *old* flexbox - // www.w3.org/TR/2009/WD-css3-flexbox-20090723/ - - tests['flexboxlegacy'] = function() { - return testPropsAll('boxDirection'); - }; - - // On the S60 and BB Storm, getContext exists, but always returns undefined - // so we actually have to call getContext() to verify - // github.com/Modernizr/Modernizr/issues/issue/97/ - - tests['canvas'] = function() { - var elem = document.createElement('canvas'); - return !!(elem.getContext && elem.getContext('2d')); - }; - - tests['canvastext'] = function() { - return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function')); - }; - - // webk.it/70117 is tracking a legit WebGL feature detect proposal - - // We do a soft detect which may false positive in order to avoid - // an expensive context creation: bugzil.la/732441 - - tests['webgl'] = function() { - return !!window.WebGLRenderingContext; - }; - - /* - * The Modernizr.touch test only indicates if the browser supports - * touch events, which does not necessarily reflect a touchscreen - * device, as evidenced by tablets running Windows 7 or, alas, - * the Palm Pre / WebOS (touch) phones. - * - * Additionally, Chrome (desktop) used to lie about its support on this, - * but that has since been rectified: crbug.com/36415 - * - * We also test for Firefox 4 Multitouch Support. - * - * For more info, see: modernizr.github.com/Modernizr/touch.html - */ - - tests['touch'] = function() { - var bool; - - if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) { - bool = true; - } else { - injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) { - bool = node.offsetTop === 9; - }); - } - - return bool; - }; - - - // geolocation is often considered a trivial feature detect... - // Turns out, it's quite tricky to get right: - // - // Using !!navigator.geolocation does two things we don't want. It: - // 1. Leaks memory in IE9: github.com/Modernizr/Modernizr/issues/513 - // 2. Disables page caching in WebKit: webk.it/43956 - // - // Meanwhile, in Firefox < 8, an about:config setting could expose - // a false positive that would throw an exception: bugzil.la/688158 - - tests['geolocation'] = function() { - return 'geolocation' in navigator; - }; - - - tests['postmessage'] = function() { - return !!window.postMessage; - }; - - - // Chrome incognito mode used to throw an exception when using openDatabase - // It doesn't anymore. - tests['websqldatabase'] = function() { - return !!window.openDatabase; - }; - - // Vendors had inconsistent prefixing with the experimental Indexed DB: - // - Webkit's implementation is accessible through webkitIndexedDB - // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB - // For speed, we don't test the legacy (and beta-only) indexedDB - tests['indexedDB'] = function() { - return !!testPropsAll("indexedDB", window); - }; - - // documentMode logic from YUI to filter out IE8 Compat Mode - // which false positives. - tests['hashchange'] = function() { - return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7); - }; - - // Per 1.6: - // This used to be Modernizr.historymanagement but the longer - // name has been deprecated in favor of a shorter and property-matching one. - // The old API is still available in 1.6, but as of 2.0 will throw a warning, - // and in the first release thereafter disappear entirely. - tests['history'] = function() { - return !!(window.history && history.pushState); - }; - - tests['draganddrop'] = function() { - var div = document.createElement('div'); - return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div); - }; - - // FF3.6 was EOL'ed on 4/24/12, but the ESR version of FF10 - // will be supported until FF19 (2/12/13), at which time, ESR becomes FF17. - // FF10 still uses prefixes, so check for it until then. - // for more ESR info, see: mozilla.org/en-US/firefox/organizations/faq/ - tests['websockets'] = function() { - return 'WebSocket' in window || 'MozWebSocket' in window; - }; - - - // css-tricks.com/rgba-browser-support/ - tests['rgba'] = function() { - // Set an rgba() color and check the returned value - - setCss('background-color:rgba(150,255,150,.5)'); - - return contains(mStyle.backgroundColor, 'rgba'); - }; - - tests['hsla'] = function() { - // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally, - // except IE9 who retains it as hsla - - setCss('background-color:hsla(120,40%,100%,.5)'); - - return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla'); - }; - - tests['multiplebgs'] = function() { - // Setting multiple images AND a color on the background shorthand property - // and then querying the style.background property value for the number of - // occurrences of "url(" is a reliable method for detecting ACTUAL support for this! - - setCss('background:url(https://),url(https://),red url(https://)'); - - // If the UA supports multiple backgrounds, there should be three occurrences - // of the string "url(" in the return value for elemStyle.background - - return (/(url\s*\(.*?){3}/).test(mStyle.background); - }; - - - - // this will false positive in Opera Mini - // github.com/Modernizr/Modernizr/issues/396 - - tests['backgroundsize'] = function() { - return testPropsAll('backgroundSize'); - }; - - tests['borderimage'] = function() { - return testPropsAll('borderImage'); - }; - - - // Super comprehensive table about all the unique implementations of - // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance - - tests['borderradius'] = function() { - return testPropsAll('borderRadius'); - }; - - // WebOS unfortunately false positives on this test. - tests['boxshadow'] = function() { - return testPropsAll('boxShadow'); - }; - - // FF3.0 will false positive on this test - tests['textshadow'] = function() { - return document.createElement('div').style.textShadow === ''; - }; - - - tests['opacity'] = function() { - // Browsers that actually have CSS Opacity implemented have done so - // according to spec, which means their return values are within the - // range of [0.0,1.0] - including the leading zero. - - setCssAll('opacity:.55'); - - // The non-literal . in this regex is intentional: - // German Chrome returns this value as 0,55 - // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632 - return (/^0.55$/).test(mStyle.opacity); - }; - - - // Note, Android < 4 will pass this test, but can only animate - // a single property at a time - // goo.gl/v3V4Gp - tests['cssanimations'] = function() { - return testPropsAll('animationName'); - }; - - - tests['csscolumns'] = function() { - return testPropsAll('columnCount'); - }; - - - tests['cssgradients'] = function() { - /** - * For CSS Gradients syntax, please see: - * webkit.org/blog/175/introducing-css-gradients/ - * developer.mozilla.org/en/CSS/-moz-linear-gradient - * developer.mozilla.org/en/CSS/-moz-radial-gradient - * dev.w3.org/csswg/css3-images/#gradients- - */ - - var str1 = 'background-image:', - str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));', - str3 = 'linear-gradient(left top,#9f9, white);'; - - setCss( - // legacy webkit syntax (FIXME: remove when syntax not in use anymore) - (str1 + '-webkit- '.split(' ').join(str2 + str1) + - // standard syntax // trailing 'background-image:' - prefixes.join(str3 + str1)).slice(0, -str1.length) - ); - - return contains(mStyle.backgroundImage, 'gradient'); - }; - - - tests['cssreflections'] = function() { - return testPropsAll('boxReflect'); - }; - - - tests['csstransforms'] = function() { - return !!testPropsAll('transform'); - }; - - - tests['csstransforms3d'] = function() { - - var ret = !!testPropsAll('perspective'); - - // Webkit's 3D transforms are passed off to the browser's own graphics renderer. - // It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in - // some conditions. As a result, Webkit typically recognizes the syntax but - // will sometimes throw a false positive, thus we must do a more thorough check: - if ( ret && 'webkitPerspective' in docElement.style ) { - - // Webkit allows this media query to succeed only if the feature is enabled. - // `@media (transform-3d),(-webkit-transform-3d){ ... }` - injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) { - ret = node.offsetLeft === 9 && node.offsetHeight === 3; - }); - } - return ret; - }; - - - tests['csstransitions'] = function() { - return testPropsAll('transition'); - }; - - - /*>>fontface*/ - // @font-face detection routine by Diego Perini - // javascript.nwbox.com/CSSSupport/ - - // false positives: - // WebOS github.com/Modernizr/Modernizr/issues/342 - // WP7 github.com/Modernizr/Modernizr/issues/538 - tests['fontface'] = function() { - var bool; - - injectElementWithStyles('@font-face {font-family:"font";src:url("https://")}', function( node, rule ) { - var style = document.getElementById('smodernizr'), - sheet = style.sheet || style.styleSheet, - cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : ''; - - bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0; - }); - - return bool; - }; - /*>>fontface*/ - - // CSS generated content detection - tests['generatedcontent'] = function() { - var bool; - - injectElementWithStyles(['#',mod,'{font:0/0 a}#',mod,':after{content:"',smile,'";visibility:hidden;font:3px/1 a}'].join(''), function( node ) { - bool = node.offsetHeight >= 3; - }); - - return bool; - }; - - - - // These tests evaluate support of the video/audio elements, as well as - // testing what types of content they support. - // - // We're using the Boolean constructor here, so that we can extend the value - // e.g. Modernizr.video // true - // Modernizr.video.ogg // 'probably' - // - // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845 - // thx to NielsLeenheer and zcorpan - - // Note: in some older browsers, "no" was a return value instead of empty string. - // It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2 - // It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5 - - tests['video'] = function() { - var elem = document.createElement('video'), - bool = false; - - // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224 - try { - if ( bool = !!elem.canPlayType ) { - bool = new Boolean(bool); - bool.ogg = elem.canPlayType('video/ogg; codecs="theora"') .replace(/^no$/,''); - - // Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546 - bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,''); - - bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,''); - } - - } catch(e) { } - - return bool; - }; - - tests['audio'] = function() { - var elem = document.createElement('audio'), - bool = false; - - try { - if ( bool = !!elem.canPlayType ) { - bool = new Boolean(bool); - bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,''); - bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,''); - - // Mimetypes accepted: - // developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements - // bit.ly/iphoneoscodecs - bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,''); - bool.m4a = ( elem.canPlayType('audio/x-m4a;') || - elem.canPlayType('audio/aac;')) .replace(/^no$/,''); - } - } catch(e) { } - - return bool; - }; - - - // In FF4, if disabled, window.localStorage should === null. - - // Normally, we could not test that directly and need to do a - // `('localStorage' in window) && ` test first because otherwise Firefox will - // throw bugzil.la/365772 if cookies are disabled - - // Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem - // will throw the exception: - // QUOTA_EXCEEDED_ERRROR DOM Exception 22. - // Peculiarly, getItem and removeItem calls do not throw. - - // Because we are forced to try/catch this, we'll go aggressive. - - // Just FWIW: IE8 Compat mode supports these features completely: - // www.quirksmode.org/dom/html5.html - // But IE8 doesn't support either with local files - - tests['localstorage'] = function() { - try { - localStorage.setItem(mod, mod); - localStorage.removeItem(mod); - return true; - } catch(e) { - return false; - } - }; - - tests['sessionstorage'] = function() { - try { - sessionStorage.setItem(mod, mod); - sessionStorage.removeItem(mod); - return true; - } catch(e) { - return false; - } - }; - - - tests['webworkers'] = function() { - return !!window.Worker; - }; - - - tests['applicationcache'] = function() { - return !!window.applicationCache; - }; - - - // Thanks to Erik Dahlstrom - tests['svg'] = function() { - return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect; - }; - - // specifically for SVG inline in HTML, not within XHTML - // test page: paulirish.com/demo/inline-svg - tests['inlinesvg'] = function() { - var div = document.createElement('div'); - div.innerHTML = ''; - return (div.firstChild && div.firstChild.namespaceURI) == ns.svg; - }; - - // SVG SMIL animation - tests['smil'] = function() { - return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate'))); - }; - - // This test is only for clip paths in SVG proper, not clip paths on HTML content - // demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg - - // However read the comments to dig into applying SVG clippaths to HTML content here: - // github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491 - tests['svgclippaths'] = function() { - return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath'))); - }; - - /*>>webforms*/ - // input features and input types go directly onto the ret object, bypassing the tests loop. - // Hold this guy to execute in a moment. - function webforms() { - /*>>input*/ - // Run through HTML5's new input attributes to see if the UA understands any. - // We're using f which is the element created early on - // Mike Taylr has created a comprehensive resource for testing these attributes - // when applied to all input types: - // miketaylr.com/code/input-type-attr.html - // spec: www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary - - // Only input placeholder is tested while textarea's placeholder is not. - // Currently Safari 4 and Opera 11 have support only for the input placeholder - // Both tests are available in feature-detects/forms-placeholder.js - Modernizr['input'] = (function( props ) { - for ( var i = 0, len = props.length; i < len; i++ ) { - attrs[ props[i] ] = !!(props[i] in inputElem); - } - if (attrs.list){ - // safari false positive's on datalist: webk.it/74252 - // see also github.com/Modernizr/Modernizr/issues/146 - attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement); - } - return attrs; - })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' ')); - /*>>input*/ - - /*>>inputtypes*/ - // Run through HTML5's new input types to see if the UA understands any. - // This is put behind the tests runloop because it doesn't return a - // true/false like all the other tests; instead, it returns an object - // containing each input type with its corresponding true/false value - - // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/ - Modernizr['inputtypes'] = (function(props) { - - for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) { - - inputElem.setAttribute('type', inputElemType = props[i]); - bool = inputElem.type !== 'text'; - - // We first check to see if the type we give it sticks.. - // If the type does, we feed it a textual value, which shouldn't be valid. - // If the value doesn't stick, we know there's input sanitization which infers a custom UI - if ( bool ) { - - inputElem.value = smile; - inputElem.style.cssText = 'position:absolute;visibility:hidden;'; - - if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) { - - docElement.appendChild(inputElem); - defaultView = document.defaultView; - - // Safari 2-4 allows the smiley as a value, despite making a slider - bool = defaultView.getComputedStyle && - defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' && - // Mobile android web browser has false positive, so must - // check the height to see if the widget is actually there. - (inputElem.offsetHeight !== 0); - - docElement.removeChild(inputElem); - - } else if ( /^(search|tel)$/.test(inputElemType) ){ - // Spec doesn't define any special parsing or detectable UI - // behaviors so we pass these through as true - - // Interestingly, opera fails the earlier test, so it doesn't - // even make it here. - - } else if ( /^(url|email)$/.test(inputElemType) ) { - // Real url and email support comes with prebaked validation. - bool = inputElem.checkValidity && inputElem.checkValidity() === false; - - } else { - // If the upgraded input compontent rejects the :) text, we got a winner - bool = inputElem.value != smile; - } - } - - inputs[ props[i] ] = !!bool; - } - return inputs; - })('search tel url email datetime date month week time datetime-local number range color'.split(' ')); - /*>>inputtypes*/ - } - /*>>webforms*/ - - - // End of test definitions - // ----------------------- - - - - // Run through all tests and detect their support in the current UA. - // todo: hypothetically we could be doing an array of tests and use a basic loop here. - for ( var feature in tests ) { - if ( hasOwnProp(tests, feature) ) { - // run the test, throw the return value into the Modernizr, - // then based on that boolean, define an appropriate className - // and push it into an array of classes we'll join later. - featureName = feature.toLowerCase(); - Modernizr[featureName] = tests[feature](); - - classes.push((Modernizr[featureName] ? '' : 'no-') + featureName); - } - } - - /*>>webforms*/ - // input tests need to run. - Modernizr.input || webforms(); - /*>>webforms*/ - - - /** - * addTest allows the user to define their own feature tests - * the result will be added onto the Modernizr object, - * as well as an appropriate className set on the html element - * - * @param feature - String naming the feature - * @param test - Function returning true if feature is supported, false if not - */ - Modernizr.addTest = function ( feature, test ) { - if ( typeof feature == 'object' ) { - for ( var key in feature ) { - if ( hasOwnProp( feature, key ) ) { - Modernizr.addTest( key, feature[ key ] ); - } - } - } else { - - feature = feature.toLowerCase(); - - if ( Modernizr[feature] !== undefined ) { - // we're going to quit if you're trying to overwrite an existing test - // if we were to allow it, we'd do this: - // var re = new RegExp("\\b(no-)?" + feature + "\\b"); - // docElement.className = docElement.className.replace( re, '' ); - // but, no rly, stuff 'em. - return Modernizr; - } - - test = typeof test == 'function' ? test() : test; - - if (typeof enableClasses !== "undefined" && enableClasses) { - docElement.className += ' ' + (test ? '' : 'no-') + feature; - } - Modernizr[feature] = test; - - } - - return Modernizr; // allow chaining. - }; - - - // Reset modElem.cssText to nothing to reduce memory footprint. - setCss(''); - modElem = inputElem = null; - - /*>>shiv*/ - /** - * @preserve HTML5 Shiv prev3.7.1 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed - */ - ;(function(window, document) { - /*jshint evil:true */ - /** version */ - var version = '3.7.0'; - - /** Preset options */ - var options = window.html5 || {}; - - /** Used to skip problem elements */ - var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i; - - /** Not all elements can be cloned in IE **/ - var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i; - - /** Detect whether the browser supports default html5 styles */ - var supportsHtml5Styles; - - /** Name of the expando, to work with multiple documents or to re-shiv one document */ - var expando = '_html5shiv'; - - /** The id for the the documents expando */ - var expanID = 0; - - /** Cached data for each document */ - var expandoData = {}; - - /** Detect whether the browser supports unknown elements */ - var supportsUnknownElements; - - (function() { - try { - var a = document.createElement('a'); - a.innerHTML = ''; - //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles - supportsHtml5Styles = ('hidden' in a); - - supportsUnknownElements = a.childNodes.length == 1 || (function() { - // assign a false positive if unable to shiv - (document.createElement)('a'); - var frag = document.createDocumentFragment(); - return ( - typeof frag.cloneNode == 'undefined' || - typeof frag.createDocumentFragment == 'undefined' || - typeof frag.createElement == 'undefined' - ); - }()); - } catch(e) { - // assign a false positive if detection fails => unable to shiv - supportsHtml5Styles = true; - supportsUnknownElements = true; - } - - }()); - - /*--------------------------------------------------------------------------*/ - - /** - * Creates a style sheet with the given CSS text and adds it to the document. - * @private - * @param {Document} ownerDocument The document. - * @param {String} cssText The CSS text. - * @returns {StyleSheet} The style element. - */ - function addStyleSheet(ownerDocument, cssText) { - var p = ownerDocument.createElement('p'), - parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement; - - p.innerHTML = 'x'; - return parent.insertBefore(p.lastChild, parent.firstChild); - } - - /** - * Returns the value of `html5.elements` as an array. - * @private - * @returns {Array} An array of shived element node names. - */ - function getElements() { - var elements = html5.elements; - return typeof elements == 'string' ? elements.split(' ') : elements; - } - - /** - * Returns the data associated to the given document - * @private - * @param {Document} ownerDocument The document. - * @returns {Object} An object of data. - */ - function getExpandoData(ownerDocument) { - var data = expandoData[ownerDocument[expando]]; - if (!data) { - data = {}; - expanID++; - ownerDocument[expando] = expanID; - expandoData[expanID] = data; - } - return data; - } - - /** - * returns a shived element for the given nodeName and document - * @memberOf html5 - * @param {String} nodeName name of the element - * @param {Document} ownerDocument The context document. - * @returns {Object} The shived element. - */ - function createElement(nodeName, ownerDocument, data){ - if (!ownerDocument) { - ownerDocument = document; - } - if(supportsUnknownElements){ - return ownerDocument.createElement(nodeName); - } - if (!data) { - data = getExpandoData(ownerDocument); - } - var node; - - if (data.cache[nodeName]) { - node = data.cache[nodeName].cloneNode(); - } else if (saveClones.test(nodeName)) { - node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode(); - } else { - node = data.createElem(nodeName); - } - - // Avoid adding some elements to fragments in IE < 9 because - // * Attributes like `name` or `type` cannot be set/changed once an element - // is inserted into a document/fragment - // * Link elements with `src` attributes that are inaccessible, as with - // a 403 response, will cause the tab/window to crash - // * Script elements appended to fragments will execute when their `src` - // or `text` property is set - return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node; - } - - /** - * returns a shived DocumentFragment for the given document - * @memberOf html5 - * @param {Document} ownerDocument The context document. - * @returns {Object} The shived DocumentFragment. - */ - function createDocumentFragment(ownerDocument, data){ - if (!ownerDocument) { - ownerDocument = document; - } - if(supportsUnknownElements){ - return ownerDocument.createDocumentFragment(); - } - data = data || getExpandoData(ownerDocument); - var clone = data.frag.cloneNode(), - i = 0, - elems = getElements(), - l = elems.length; - for(;i>shiv*/ - - // Assign private properties to the return object with prefix - Modernizr._version = version; - - // expose these for the plugin API. Look in the source for how to join() them against your input - /*>>prefixes*/ - Modernizr._prefixes = prefixes; - /*>>prefixes*/ - /*>>domprefixes*/ - Modernizr._domPrefixes = domPrefixes; - Modernizr._cssomPrefixes = cssomPrefixes; - /*>>domprefixes*/ - - /*>>mq*/ - // Modernizr.mq tests a given media query, live against the current state of the window - // A few important notes: - // * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false - // * A max-width or orientation query will be evaluated against the current state, which may change later. - // * You must specify values. Eg. If you are testing support for the min-width media query use: - // Modernizr.mq('(min-width:0)') - // usage: - // Modernizr.mq('only screen and (max-width:768)') - Modernizr.mq = testMediaQuery; - /*>>mq*/ - - /*>>hasevent*/ - // Modernizr.hasEvent() detects support for a given event, with an optional element to test on - // Modernizr.hasEvent('gesturestart', elem) - Modernizr.hasEvent = isEventSupported; - /*>>hasevent*/ - - /*>>testprop*/ - // Modernizr.testProp() investigates whether a given style property is recognized - // Note that the property names must be provided in the camelCase variant. - // Modernizr.testProp('pointerEvents') - Modernizr.testProp = function(prop){ - return testProps([prop]); - }; - /*>>testprop*/ - - /*>>testallprops*/ - // Modernizr.testAllProps() investigates whether a given style property, - // or any of its vendor-prefixed variants, is recognized - // Note that the property names must be provided in the camelCase variant. - // Modernizr.testAllProps('boxSizing') - Modernizr.testAllProps = testPropsAll; - /*>>testallprops*/ - - - /*>>teststyles*/ - // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards - // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... }) - Modernizr.testStyles = injectElementWithStyles; - /*>>teststyles*/ - - - /*>>prefixed*/ - // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input - // Modernizr.prefixed('boxSizing') // 'MozBoxSizing' - - // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style. - // Return values will also be the camelCase variant, if you need to translate that to hypenated style use: - // - // str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-'); - - // If you're trying to ascertain which transition end event to bind to, you might do something like... - // - // var transEndEventNames = { - // 'WebkitTransition' : 'webkitTransitionEnd', - // 'MozTransition' : 'transitionend', - // 'OTransition' : 'oTransitionEnd', - // 'msTransition' : 'MSTransitionEnd', - // 'transition' : 'transitionend' - // }, - // transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ]; - - Modernizr.prefixed = function(prop, obj, elem){ - if(!obj) { - return testPropsAll(prop, 'pfx'); - } else { - // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame' - return testPropsAll(prop, obj, elem); - } - }; - /*>>prefixed*/ - - - /*>>cssclasses*/ - // Remove "no-js" class from element, if it exists: - docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') + - - // Add the new classes to the element. - (enableClasses ? ' js ' + classes.join(' ') : ''); - /*>>cssclasses*/ - - return Modernizr; - -})(this, this.document); diff --git a/BeWoPlanerMobil/Scripts/view-scripts/main.js b/BeWoPlanerMobil/Scripts/view-scripts/main.js index d8c91f634..4c2cc59d7 100644 --- a/BeWoPlanerMobil/Scripts/view-scripts/main.js +++ b/BeWoPlanerMobil/Scripts/view-scripts/main.js @@ -566,7 +566,13 @@ function getStartAndEndDate() { // Bei leeren Start- und Endfeldern. Muss ein Dummydate zurückgeben, // damit das Speichern ohne Angabe der Start- und Endzeit möglich ist. if($("#start-time").val().length === 0 || $("#end-time").val().length === 0) { - var dummyDate = moment(new Date()); + var bareDate = new Date(); + + bareDate.setHours(0); + bareDate.setMinutes(0); + bareDate.setSeconds(1); + + var dummyDate = moment(bareDate); return [dummyDate, dummyDate]; } @@ -587,7 +593,7 @@ function getStartAndEndDate() { var endTime = endTimePicker.datetimepicker("date"); var startDate = startDatePicker.datetimepicker("date"); var endDate = endDatePicker.datetimepicker("date"); - + var a = startDate === undefined || startDate === null || !startDate.isValid(); var b = endDatePicker.length === 0 ? false : endDate === undefined || endDate === null || !endDate.isValid(); var c = startTime === undefined || startTime === null || !startTime.isValid(); diff --git a/BeWoPlanerMobil/Scripts/view-scripts/report.js b/BeWoPlanerMobil/Scripts/view-scripts/report.js index c58ceea6d..2b83c3bc1 100644 --- a/BeWoPlanerMobil/Scripts/view-scripts/report.js +++ b/BeWoPlanerMobil/Scripts/view-scripts/report.js @@ -45,15 +45,19 @@ function calculateDays() { $.get(changeDateSelectionUrl, { startDayString: startDay, endDayString: endDay, monthString: month, yearString: year}); } -function initializeReportSignature() { +function initializeReportSignature(overwrite) { $("#report-form-container").hide(); $("#report-signature-container").addClass("d-block"); - var customer = $("#customers-drop-down option:selected").text(); - var month = $("#month-select option:selected").text(); - var year = $("#year-select option:selected").text(); + if(overwrite) { + $("#overwriting-employee-signature-alert").addClass("d-block"); + } - $("#report-info-column").html("Unterschrift für erbrachte Leistungen von " + customer + " im " + month + " " + year); + var text = $("#signature-canvas-information").val(); + + var serviceRecordCount = $("#service-record-count").val(); + + $("#report-info-column").html("Unterschrift für " + serviceRecordCount + " erbrachte Leistungen von " + text); resizeCanvas("#report-sketch-pad", "#report-canvas-row"); @@ -65,7 +69,7 @@ function initializeReportSignature() { var clearButton = document.getElementById("clear-report-canvas-btn"); var cancelButton = document.getElementById("cancel-report-signature-btn"); - saveButton.addEventListener("click", function(event) { + saveButton.addEventListener("click", function() { var clonedCanvas = trimCanvas(cloneCanvas(document.getElementById("report-sketch-pad"))); var context = clonedCanvas.getContext("2d"); @@ -78,79 +82,40 @@ function initializeReportSignature() { showMessagePopupWithCallback("Unterschrift speichern", "Mit dem Speichern der Unterschrift ist es nicht mehr möglich, die betroffenen Einträge der Zeiterfassung zu ändern.", function() { showSpinner(); - var test = getValidateEmployeeSignatureUrl(); + var signatureCreationUrl = getCreateSignatureForServiceOverviewUrl(); - $.get(test).done(function(result) { - // Falls true bisherige Unterschrift ersetzen - if(result === undefined || result === null) { - logError("employee signature validation result is undefined"); - return; - } + showSpinner(); - if(result === "True") { - showWarningMessageBox("Speichern", - "Für " + month + " " + year + " existiert bereits eine oder mehrere Mitarbeiterunterschriften. Möchten Sie sie ersetzen?", - function() { - var url = getCreateEmployeeSignatureForServiceOverviewUrl(); + $.post(signatureCreationUrl, { base64SignatureString: dataUrl, customerOidString: null, isCustomerSignature: false, overwrite: overwrite }).done(function(json) { + hideSpinner(); - $.post(url, { base64SignatureString: dataUrl }).done(function(json) { - hideSpinner(); - - if (isEmptyOrSpaces(json)) { - $("#signature-container").removeClass("d-block"); - $("#main-container, #checkbox-container").show(); - showMessagePopupWithCallback("Unterschrift", - "Die Unterschrift wurde erfolgreich gespeichert.", - function() { - showSpinner(); - location.reload(); - }, - true); - } else { - showMessagePopup("Fehler", json); - signaturePad.clear(); - } - }); - }, - false); + if(isEmptyOrSpaces(json)) { + // Ist umbenannt in report-signature-container + $("#signature-container").removeClass("d-block"); + $("#main-container, #checkbox-container").show(); + showMessagePopupWithCallback("Unterschrift", "Die Unterschrift wurde erfolgreich gespeichert.", function() { + showSpinner(); + location.reload(); + }, true); } else { - var url = getCreateEmployeeSignatureForServiceOverviewUrl(); - - $.post(url, { base64SignatureString: dataUrl }).done(function(json) { - hideSpinner(); - - if(isEmptyOrSpaces(json)) { - $("#signature-container").removeClass("d-block"); - $("#main-container, #checkbox-container").show(); - showMessagePopupWithCallback("Unterschrift", "Die Unterschrift wurde erfolgreich gespeichert.", function() { - showSpinner(); - location.reload(); - }, true); - } else { - showMessagePopup("Fehler", json); - signaturePad.clear(); - } - }); + showMessagePopup("Fehler", json); + signaturePad.clear(); } }); - }, false); }); - clearButton.addEventListener("click", function(event) { + clearButton.addEventListener("click", function() { signaturePad.clear(); }); - cancelButton.addEventListener("click", function(event) { + cancelButton.addEventListener("click", function() { showMessagePopupWithCallback("Unterschrift", "Sind Sie sicher, dass Sie die Unterschrift nicht speichern möchten?", function() { $("#report-signature-container").removeClass("d-block"); $("#report-form-container").show(); signaturePad.clear(); - - //TODO: Notwendigkeit prüfen - //$.get(getResetSignatureImageUrl()); }, false); }); } @@ -192,53 +157,6 @@ function checkForExistingSignature() { endDayString: endDay, monthString: month, yearString: year - }, - function(result1) { - if (result1!=null && result1.length > 1) { - var jason = $.parseJSON(result1); - - if (jason === true) { - var customerOid = $("#customers-drop-down option:selected").val(); - - var monthName = $("#month-select option:selected").text(); - - var isCostbearerChecked = $("#selected-organisation-cb").is(":checked"); - - var costbearerOid = isCostbearerChecked === true ? $("#organisation-select option:selected").val() : null; - - logDebug($("#organisation-select option:selected").val()); - - var url = getCheckForEmployeeSignatureUrl(); - - $.get(url, - { - customerOidString: customerOid, - monthString: month, - yearString: year, - startDayString: startDay, - endDayString: endDay, - costbearerOidString: costbearerOid - }, - function(result) { - if(result === null || result === undefined || result.length <= 1) { - return; - } - - var hasSignatures = $.parseJSON(result); - - if(hasSignatures === true) { - $("#warning-message-container").removeClass("d-none"); - $("#warning-message-container").addClass("d-block"); - $("#warning-message-container").html("Für " + monthName + " " + year + " existiert bereits eine Mitarbeiterunterschrift."); - } else { - $("#warning-message-container").empty(); - $("#warning-message-container").removeClass("d-block"); - $("#warning-message-container").addClass("d-none"); - } - } - ); - } - } }); } @@ -298,6 +216,109 @@ function filterCheckBoxChange() { }); } -function validateReportForm() { +function onCustomerSelectionChange() { + var url = getSetCustomerUrl(); + var selectedCustomerOid = $("#customers-drop-down option:selected").val(); + + $.get(url, { customerOid: selectedCustomerOid}).done(function() { + checkForExistingSignature(); + }); +} + +function openCustomerSignaturePopup(numberOfEntries, customerName, timeSpan, customerOid, overwrite) { + // Popup anzeigen + $("#report-form-container").hide(); + + $("#report-customer-signature-container").addClass("d-block"); + + $("#report-customer-info-column").html("Unterschrift für " + numberOfEntries + " erbrachte Leistungen von " + customerName + " (" + timeSpan + ")"); + + if (overwrite) { + $("#overwriting-customer-signature-alert").addClass("d-block"); + } + + resizeCanvas("#report-customer-sketch-pad", "#report-customer-canvas-row"); + + var canvas = document.getElementById("report-customer-sketch-pad"); + + var signaturePad = new SignaturePad(canvas, { backgroundColor: "rgba(255, 255, 255, 0)" }); + + var saveButton = document.getElementById("save-report-customer-signature-btn"); + var clearButton = document.getElementById("clear-report-customer-canvas-btn"); + var cancelButton = document.getElementById("cancel-report-customer-signature-btn"); + + saveButton.addEventListener("click", function() { + var clonedCanvas = trimCanvas(cloneCanvas(document.getElementById("report-customer-sketch-pad"))); + + var context = clonedCanvas.getContext("2d"); + context.globalCompositeOperation = "destination-over"; + context.fillStyle = "white"; + context.fillRect(0, 0, clonedCanvas.width, clonedCanvas.height); + + var dataUrl = clonedCanvas.toDataURL("image/png"); + + showMessagePopupWithCallback("Unterschrift speichern", "Mit dem Speichern der Unterschrift ist es nicht mehr möglich, die betroffenen Einträge der Zeiterfassung zu ändern.", + function() { + var url = getCreateSignatureForServiceOverviewUrl(); + + $.post(url, { base64SignatureString: dataUrl, customerOidString: customerOid, isCustomerSignature: true, overwrite: overwrite }).done(function(json) { + hideSpinner(); + + if(isEmptyOrSpaces(json)) { + showMessagePopupWithCallback("Unterschrift", + "Die Unterschrift wurde erfolgreich gespeichert.", + function() { + showSpinner(); + location.reload(); + }, + true); + } else { + showMessagePopup("Fehler", json); + signaturePad.clear(); + } + }); + }, + false); + }); + + clearButton.addEventListener("click", function() { + signaturePad.clear(); + }); + + cancelButton.addEventListener("click", function() { + showMessagePopupWithCallback("Unterschrift", "Sind Sie sicher, dass Sie die Unterschrift nicht speichern möchten?", + function() { + $("#report-customer-signature-container").removeClass("d-block"); + $("#overwriting-customer-signature-alert").removeClass("d-block"); + $("#report-form-container").show(); + + signaturePad.clear(); + }, false); + }); +} + +function showCustomerSignature(signatureOid) { + loadConfirmationReceiptSignature(signatureOid); +} + +function loadConfirmationReceiptSignature(signatureOid) { + var url = getLoadConfirmationReceiptSignatureUrl(); + + $.get(url, { signatureOidString: signatureOid }).done(function(json) { + $("#signature-img-popup").addClass("d-block"); + + $("#signature-holder-img").prop("src", json); + }); +} + +function hideConfirmationReceiptSignature() { + $("#signature-img-popup").removeClass("d-block"); + $(".modal-backdrop").hide(); +} + +function showEmployeeSignature(signatureOid) { + $("#employee-signature-list").hide(); + + loadConfirmationReceiptSignature(signatureOid); } \ No newline at end of file diff --git a/BeWoPlanerMobil/Util/QuittierungsbelegResult.cs b/BeWoPlanerMobil/Util/QuittierungsbelegResult.cs index 4c21c396c..040872012 100644 --- a/BeWoPlanerMobil/Util/QuittierungsbelegResult.cs +++ b/BeWoPlanerMobil/Util/QuittierungsbelegResult.cs @@ -11,11 +11,20 @@ namespace BeWoPlanerMobil.Util public List Items { get; } - public QuittierungsbelegResult(string customerName, List items) + public long CustomerOid { get; } + + public bool HasCustomerSignature { get; } + + public long? CustomerSignatureOid { get; } + + public QuittierungsbelegResult(string customerName, List items, long customerOid, bool hasCustomerSignature, long? customerSignatureOid) { CustomerName = customerName; Items = items; Identifier = Guid.NewGuid(); + CustomerOid = customerOid; + HasCustomerSignature = hasCustomerSignature; + CustomerSignatureOid = customerSignatureOid; } } } \ No newline at end of file diff --git a/BeWoPlanerMobil/Util/ReportUtils/ConfirmationReceiptObject.cs b/BeWoPlanerMobil/Util/ReportUtils/ConfirmationReceiptObject.cs index 076b62e3a..027d43449 100644 --- a/BeWoPlanerMobil/Util/ReportUtils/ConfirmationReceiptObject.cs +++ b/BeWoPlanerMobil/Util/ReportUtils/ConfirmationReceiptObject.cs @@ -1,4 +1,6 @@ using System.Collections.Generic; +using BS.Shared.DataContracts; +using BS.Shared.Extensions; namespace BeWoPlanerMobil.Util.ReportUtils { @@ -8,10 +10,34 @@ namespace BeWoPlanerMobil.Util.ReportUtils public List ConfirmationReceiptResultList { get; } - public ConfirmationReceiptObject(string information, List confirmationReceiptResultList) + public int NumberOfServiceRecords + { + get + { + var count = 0; + + ConfirmationReceiptResultList.DoForEach(crr => count += crr.Items.Count); + + return count; + } + } + + public string SignatureCanvasInformation { get; set; } + + public string TimeSpanString { get; set; } + + public bool HasEmployeeSignature { get; } + + public List EmployeeSignatures { get; } + + public ConfirmationReceiptObject(string information, List confirmationReceiptResultList, string signatureCanvasInformation, string timeSpanString, bool hasEmployeeSignature, List employeeSignatures) { Information = information; ConfirmationReceiptResultList = confirmationReceiptResultList; + SignatureCanvasInformation = signatureCanvasInformation; + TimeSpanString = timeSpanString; + HasEmployeeSignature = hasEmployeeSignature; + EmployeeSignatures = employeeSignatures; } } } \ No newline at end of file diff --git a/BeWoPlanerMobil/Views/Report/Report.cshtml b/BeWoPlanerMobil/Views/Report/Report.cshtml index 3c740564c..34570e12a 100644 --- a/BeWoPlanerMobil/Views/Report/Report.cshtml +++ b/BeWoPlanerMobil/Views/Report/Report.cshtml @@ -5,18 +5,6 @@ } -@* -TODO: Datumsvalidierung, Standartdatum zu Beginn auf den ersten bis zum letzten Tag des vorherigen Monats setzen -*@ -
@using(Html.BeginForm("CreateServiceOverview", "Report", FormMethod.Post)) { - -
@@ -64,7 +58,7 @@ TODO: Datumsvalidierung, Standartdatum zu Beginn auf den ersten bis zum letzten
@Html.LabelFor(m => m.SelectedCustomerOid) - @Html.DropDownListFor(m => m.SelectedCustomerOid, Model.CustomerListItems, new { id = "customers-drop-down", @class = "form-control", onchange = "checkForExistingSignature()" }) + @Html.DropDownListFor(m => m.SelectedCustomerOid, Model.CustomerListItems, new { id = "customers-drop-down", @class = "form-control", onchange = "onCustomerSelectionChange()" })
@@ -102,7 +96,7 @@ TODO: Datumsvalidierung, Standartdatum zu Beginn auf den ersten bis zum letzten
- @Html.DropDownListFor(m => m.SelectedOrganisationOid, Model.OrganisationItems, new { id = "organisation-select", @class = "form-control", onchange="filterCheckBoxChange()" }) + @Html.DropDownListFor(m => m.SelectedOrganisationOid, Model.OrganisationItems, new { id = "organisation-select", @class = "form-control", onchange = "filterCheckBoxChange()" })
@@ -131,19 +125,19 @@ TODO: Datumsvalidierung, Standartdatum zu Beginn auf den ersten bis zum letzten
@Html.LabelFor(m => m.SelectedStartDay) - @Html.DropDownListFor(m => m.SelectedStartDay, Model.Days, new { id = "start-day-select", onchange = "checkForExistingSignature()", @class = "form-control"}) + @Html.DropDownListFor(m => m.SelectedStartDay, Model.Days, new { id = "start-day-select", onchange = "checkForExistingSignature()", @class = "form-control" })
@Html.LabelFor(m => m.SelectedEndDay) - @Html.DropDownListFor(m => m.SelectedEndDay, Model.Days, new { id = "end-day-select", onchange = "checkForExistingSignature()", @class = "form-control"}) + @Html.DropDownListFor(m => m.SelectedEndDay, Model.Days, new { id = "end-day-select", onchange = "checkForExistingSignature()", @class = "form-control" })
@Html.LabelFor(m => m.SelectedYear) - @Html.DropDownListFor(m => m.SelectedYear, Model.Years, new { id = "year-select", onchange = "onMonthOrYearChange()", @class = "form-control"}) + @Html.DropDownListFor(m => m.SelectedYear, Model.Years, new { id = "year-select", onchange = "onMonthOrYearChange()", @class = "form-control" })
@@ -176,17 +170,46 @@ TODO: Datumsvalidierung, Standartdatum zu Beginn auf den ersten bis zum letzten @Model.ConfirmationReceiptObject.Information
+ + + foreach(var result in Model.ConfirmationReceiptObject.ConfirmationReceiptResultList) {
-
-
- -
+
+
+
+
+ +
+
+
+ @{ + var methodName = "openCustomerSignaturePopup(" + + $"'{result.Items.Count}', " + + $"'{result.CustomerName}', " + + $"'{Model.ConfirmationReceiptObject.TimeSpanString}', " + + $"'{result.CustomerOid}', {result.HasCustomerSignature.ToString().ToLower()})"; + } + + + + @{ + if(result.HasCustomerSignature) + { + + } + } +
+
@@ -247,20 +270,75 @@ TODO: Datumsvalidierung, Standartdatum zu Beginn auf den ersten bis zum letzten
+ } - - } + if(Model?.ConfirmationReceiptObject?.ConfirmationReceiptResultList?.Count > 0) + { + if(Model?.ConfirmationReceiptObject?.EmployeeSignatures?.Count > 0) + { +
+
+
+ +
+
+
- if(Model?.ConfirmationReceiptObject?.ConfirmationReceiptResultList?.Count > 0) - { -
-
- -
-
- -
-
+ + + } +
+ @if(Model?.ConfirmationReceiptObject?.HasEmployeeSignature ?? false) + { +
+ +
+ } +
+ +
+
+ +
+
} }
@@ -268,6 +346,7 @@ TODO: Datumsvalidierung, Standartdatum zu Beginn auf den ersten bis zum letzten
+
@@ -278,6 +357,13 @@ TODO: Datumsvalidierung, Standartdatum zu Beginn auf den ersten bis zum letzten
+
+
+ +
+
@@ -290,4 +376,62 @@ TODO: Datumsvalidierung, Standartdatum zu Beginn auf den ersten bis zum letzten
- \ No newline at end of file + + + + + +
+
+
+
+ +

Unterschrift

+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ + +
+
+
+
+ + + + + + \ No newline at end of file diff --git a/BeWoPlanerMobil/Views/Shared/_Layout.cshtml b/BeWoPlanerMobil/Views/Shared/_Layout.cshtml index 84d4b3bf1..edc9ac42e 100644 --- a/BeWoPlanerMobil/Views/Shared/_Layout.cshtml +++ b/BeWoPlanerMobil/Views/Shared/_Layout.cshtml @@ -4,7 +4,9 @@ - + + + @ViewBag.Title @@ -19,7 +21,6 @@ - diff --git a/BeWoPlanerMobil/Web.config b/BeWoPlanerMobil/Web.config index 87523fa97..e4d1525fa 100644 --- a/BeWoPlanerMobil/Web.config +++ b/BeWoPlanerMobil/Web.config @@ -1,4 +1,4 @@ - +
@@ -197,6 +197,10 @@ + + + + diff --git a/BeWoPlanerMobil/packages.config b/BeWoPlanerMobil/packages.config index c9a6f812b..c6ac3dc5c 100644 --- a/BeWoPlanerMobil/packages.config +++ b/BeWoPlanerMobil/packages.config @@ -25,7 +25,6 @@ - diff --git a/Data/Access/SearchDAO.cs b/Data/Access/SearchDAO.cs index 4d930dab3..1d56b3100 100644 --- a/Data/Access/SearchDAO.cs +++ b/Data/Access/SearchDAO.cs @@ -21,6 +21,7 @@ using BS.Shared; using BS.Shared.DataContracts; using DevExpress.XtraScheduler; using DevExpress.XtraScheduler.Compatibility; +using NHibernate.Transform; using static System.String; using Appointment = BeWo.Data.Entities.Appointment; using Login = BeWo.Data.Entities.Login; @@ -3768,11 +3769,15 @@ namespace BeWo.Data.Access return result; } + // TODO 16.02.2021: Alias für EmployeeOid erstellen? public IList GetConfirmationReceiptSignaturesByEmployee(long employeeOid, DateTimeSpan timeSpan) { var liste = CreateCriteria() + .Add(Restrictions.Eq(nameof(ConfirmationReceiptSignature.SignatureType), SignatureType.Employee)) .Add(Restrictions.Eq(nameof(BeWoEntityBase.IsActive), ActivationTypeId.Active)) - .Add(Restrictions.Eq(nameof(ConfirmationReceiptSignature.EmployeeOid), employeeOid)) + //.Add(Restrictions.Eq(nameof(ConfirmationReceiptSignature.EmployeeOid), employeeOid)) + .CreateAlias(nameof(ConfirmationReceiptSignature.Employee), "e", JoinType.InnerJoin) + .Add(Restrictions.Eq(nameof(BeWoEntityBase.Oid), employeeOid)) .CreateAlias(nameof(ConfirmationReceiptSignature.ServiceRecords), "s", JoinType.InnerJoin) .Add(CreateBetweenDateTimesCriterion(timeSpan.StartDateTime, timeSpan.EndDateTime, "s.Start", "s.End")).List(); @@ -3909,28 +3914,6 @@ namespace BeWo.Data.Access return result; } - public bool HasEmployeeSignatureForCustomerInTimeSpan(long customerOid, DateTimeSpan timeSpan) - { - var start = timeSpan.StartDate.GetFirstOfMonth(); - var end = timeSpan.EndDate.GetLastOfMonth(); - - var timeSpanCriterion = CreateBetweenDateTimesCriterion(start, end, $"serviceRecord.{nameof(ServiceRecord.Start)}", $"serviceRecord.{nameof(ServiceRecord.End)}"); - - var criteria = CreateCriteria() - .CreateAlias(nameof(ConfirmationReceiptSignature.ServiceRecords), "serviceRecord") - .Add(Restrictions.Eq($"serviceRecord.{nameof(ServiceRecord.CustomerOid)}", customerOid)) - .Add(timeSpanCriterion); - - var hasAny = criteria.List().Any(); - - return hasAny; - } - - public bool HasEmployeeSignaturesForServiceRecord(long serviceRecordOid) - { - return GetConfirmationReceiptSignaturesByServiceRecord(serviceRecordOid).Any(); - } - public IList GetAllQuittierungsbelegStatusForMonth(DateTime start, DateTime ende) { DateTime begin = new DateTime(start.Year, start.Month, start.Day); @@ -3957,19 +3940,23 @@ namespace BeWo.Data.Access return crit.List(); } + // TODO 16.02.2021: Alias für EmployeeOid erstellen? public bool HasConfirmationReceiptSignaturesByEmployeeAndServiceRecords(long employeeOid, IEnumerable serviceRecordOids) { var criteria = CreateCriteria() - .Add(Restrictions.Eq(nameof(ConfirmationReceiptSignature.EmployeeOid), employeeOid)) + .Add(Restrictions.Eq(nameof(ConfirmationReceiptSignature.SignatureType), SignatureType.Employee)) + //.Add(Restrictions.Eq(nameof(ConfirmationReceiptSignature.EmployeeOid), employeeOid)) + .CreateAlias(nameof(ConfirmationReceiptSignature.Employee), "e", JoinType.InnerJoin) + .Add(Restrictions.Eq(nameof(BeWoEntityBase.Oid), employeeOid)) .CreateAlias(nameof(ConfirmationReceiptSignature.ServiceRecords), "serviceRecord") - .Add(Restrictions.In("serviceRecord.Oid", serviceRecordOids.ToList())); + .Add(Restrictions.In("serviceRecord.Oid", serviceRecordOids.ToList())); var hasSignatures = criteria.List().Any(); return hasSignatures; } - public bool HasConfirmationReceiptSignatureByDateAndCustomer(long customerOid, DateTimeSpan timeSpan) + public bool HasConfirmationReceiptSignatureByDateAndCustomer(long customerOid, DateTimeSpan timeSpan, SignatureType signatureType) { var start = timeSpan.StartDate; var end = timeSpan.EndDate; @@ -3977,6 +3964,7 @@ namespace BeWo.Data.Access var timeSpanCriterion = CreateBetweenDateTimesCriterion(start, end, $"serviceRecord.{nameof(ServiceRecord.Start)}", $"serviceRecord.{nameof(ServiceRecord.End)}"); var criteria = CreateCriteria() + .Add(Restrictions.Eq(nameof(ConfirmationReceiptSignature.SignatureType), signatureType)) .CreateAlias(nameof(ConfirmationReceiptSignature.ServiceRecords), "serviceRecord") .Add(Restrictions.Eq($"serviceRecord.{nameof(ServiceRecord.CustomerOid)}", customerOid)) .Add(timeSpanCriterion); @@ -4031,12 +4019,16 @@ namespace BeWo.Data.Access return result; } + // TODO 16.02.2021: Alias für EmployeeOid erstellen? public IEnumerable FindConfirmationReceiptSignaturesByEmployeeAndServiceRecords(long employeeOid, IEnumerable serviceRecordOids) { var criteria = CreateCriteria() - .Add(Restrictions.Eq(nameof(ConfirmationReceiptSignature.EmployeeOid), employeeOid)) + .Add(Restrictions.Eq(nameof(ConfirmationReceiptSignature.SignatureType), SignatureType.Employee)) + //.Add(Restrictions.Eq(nameof(ConfirmationReceiptSignature.EmployeeOid), employeeOid)) + .CreateAlias(nameof(ConfirmationReceiptSignature.Employee), "e", JoinType.InnerJoin) + .Add(Restrictions.Eq(nameof(BeWoEntityBase.Oid), employeeOid)) .CreateAlias(nameof(ConfirmationReceiptSignature.ServiceRecords), "serviceRecord") - .Add(Restrictions.In("serviceRecord.Oid", serviceRecordOids.ToList())); + .Add(Restrictions.In("serviceRecord.Oid", serviceRecordOids.ToList())); return criteria.List(); } @@ -4171,8 +4163,6 @@ namespace BeWo.Data.Access }); }); - var customerOids = user.Employee.Employee2CustomerList.Where(employee2Customer => employee2Customer.Customer.Oid.HasValue).Select(employee2Customer => employee2Customer.Customer.Oid.Value).Distinct().ToList(); - // Der ApplicationUser darf alles Sehen oder alle Hilfepläne if(user.CheckForAtLeastOneRight(new List {UserRightType.ViewAll, UserRightType.SupportConcept_ViewAllSupportConcepts}) && supportConceptFilter == CustomerFilterEnum.All) { @@ -4185,6 +4175,8 @@ namespace BeWo.Data.Access return GetAllActiveSupportConceptsByCustomers(teamCustomerOids, true).ToList(); } + var customerOids = user.Employee.Employee2CustomerList.Where(employee2Customer => employee2Customer.Customer.Oid.HasValue).Select(employee2Customer => employee2Customer.Customer.Oid.Value).Distinct().ToList(); + return GetAllActiveSupportConceptsByCustomers(customerOids, true).ToList(); } @@ -4196,72 +4188,162 @@ namespace BeWo.Data.Access return c.List(); } - public bool HasConfirmationReceiptSignature(IEnumerable customerOids, long? employeeOid, long? costbearerOid, long? serviceCategoryOid, DateTimeSpan timeSpan) + public bool HasConfirmationReceiptSignature(IList serviceRecordOids, SignatureType signatureType) { - var criteria = CreateCriteriaIsActive(); + // Prüfen, ob alle ServiceRecords mit ein und derselben Mitarbeiterunterschrift verknüpft sind. + // Eine Unterschrift kann mehrere ServiceRecords in der LinkListe haben, die nicht in der zu prüfenden Oid-Liste sind. + var c = CreateCriteriaIsActive() + .Add(Restrictions.Eq(nameof(ConfirmationReceiptSignature.SignatureType), signatureType)) + .CreateAlias(nameof(ConfirmationReceiptSignature.ServiceRecords), "sr", JoinType.InnerJoin) + .Add(Restrictions.In($"sr.{nameof(BeWoEntityBase.Oid)}", serviceRecordOids.ToArray())); - var timeSpanCriterion = CreateBetweenDateTimesCriterion(timeSpan.StartDate, timeSpan.EndDate, nameof(ServiceRecord.Start), nameof(ServiceRecord.End)); + var signatures = c.List().ToList(); - criteria.Add(timeSpanCriterion); + var result = false; - if(costbearerOid.HasValue) + if(serviceRecordOids.Any() && signatures.Any()) { - criteria = criteria.CreateAlias(nameof(ServiceRecord.CostBearer2SupportConcept), "c2sc", JoinType.InnerJoin) - .CreateAlias($"c2sc.{nameof(CostBearer2SupportConcept.CostBearer)}", "c", JoinType.InnerJoin) - .Add(Restrictions.Eq($"c.{nameof(BeWoEntityBase.Oid)}", costbearerOid)); + var blubb = new List(); + signatures.DoForEach(s => { + s.ServiceRecords.DoForEach(sr => + { + if(sr.Oid.HasValue) + { + blubb.AddIfNotIn(sr.Oid.Value); + } + }); + }); + + result = serviceRecordOids.ContainsSameItemsAs(blubb); } - if(employeeOid.HasValue) - { - criteria.Add(Restrictions.Eq(nameof(ServiceRecord.EmployeeOid), employeeOid)); - } + return result; + } - if(serviceCategoryOid.HasValue) - { - criteria = criteria.CreateAlias(nameof(ServiceRecord.ServiceDescription), "sd", JoinType.InnerJoin) - .CreateAlias($"sd.{nameof(ServiceDescription.ServiceCategory)}", "category", JoinType.InnerJoin) - .Add(Restrictions.Eq($"category.{nameof(BeWoEntityBase.Oid)}", serviceCategoryOid)); - } + // Methode, die herausfindet, ob eine Liste mit ServiceRecordOids zu genau einer Mitarbeiterunterschrift gehört + public ConfirmationReceiptSignature GetConfirmationReceiptSignatureForServiceRecords(List serviceRecordOids, SignatureType signatureType) + { + var c = CreateCriteriaIsActive() + .Add(Restrictions.Eq(nameof(ConfirmationReceiptSignature.SignatureType), signatureType)) + .CreateAlias(nameof(ConfirmationReceiptSignature.ServiceRecords), "sr", JoinType.InnerJoin) + .Add(Restrictions.In($"sr.{nameof(BeWoEntityBase.Oid)}", serviceRecordOids.ToArray())); - criteria.Add(Restrictions.In(nameof(ServiceRecord.CustomerOid), customerOids.ToArray())); + var signatures = c.List().ToList(); - var list = criteria.List().Where(w => w.ServiceDescription.ServiceCategory.IsBillable).ToList(); + var relatedServiceRecordOids = new List(); + signatures.DoForEach(s => relatedServiceRecordOids.AddRangeIfElementsNotIn(s.ServiceRecords.Select(x => x.Oid.Value))); - var debugText = Empty; - list.DoForEach(s => - { - var debugString = $"{s.Oid} {s.Start:dd.MM.yyyy HH:mm} - {s.End:dd.MM.yyyy HH:mm}; {s.CostBearer2SupportConcept.CostBearer.Organisation.Name}; {s.Customer.Person.LastNameFirstName}; {s.Employee.Person.LastNameFirstName}; {s.ServiceDescription.ServiceCategory.Name}"; + var containsItems = relatedServiceRecordOids.ContainsItems(serviceRecordOids); - if(s.GroupOid.HasValue) - { - debugString += $" Gruppenbuchung({s.GroupOid})"; - } + return containsItems ? signatures.FirstOrDefault() : null; + } - debugString += "\n"; - debugText += debugString; - }); + public List LoadConfirmationReceiptSignaturesByServiceRecordOids(IList serviceRecordOids, SignatureType signatureType) + { + var c = CreateCriteriaIsActive() + .Add(Restrictions.Eq(nameof(ConfirmationReceiptSignature.SignatureType), signatureType)) + .CreateAlias(nameof(ConfirmationReceiptSignature.ServiceRecords), "sr", JoinType.InnerJoin) + .Add(Restrictions.In($"sr.{nameof(BeWoEntityBase.Oid)}", serviceRecordOids.ToArray())); - var serviceRecordOids = list.Where(serviceRecord => serviceRecord.Oid.HasValue).Select(serviceRecord => serviceRecord.Oid.Value); + // Der ResultTransformer erzeugt ein SELECT DISTINCT für den Roottypen (ConfirmationReceiptSignature) + c.SetResultTransformer(new DistinctRootEntityResultTransformer()); - /* - * var liste = CreateCriteriaIsActive() - .Add(Restrictions.Eq(nameof(ConfirmationReceiptSignature.EmployeeOid), employeeOid)) - .CreateAlias(nameof(ConfirmationReceiptSignature.ServiceRecords), "s", JoinType.InnerJoin) - .Add(CreateBetweenDateTimesCriterion(timeSpan.StartDateTime, timeSpan.EndDateTime, "s.Start", "s.End")) - */ + var result = c.List().ToList(); + return result; + } + + public bool HasConfirmationReceiptSignaturesByCustomerAndServiceRecords(long customerOid, IEnumerable serviceRecordOids) + { + var criteria = CreateCriteria() + .Add(Restrictions.Eq(nameof(ConfirmationReceiptSignature.SignatureType), SignatureType.Customer)) + .Add(Restrictions.Eq(nameof(ConfirmationReceiptSignature.CustomerOid), customerOid)) + .CreateAlias(nameof(ConfirmationReceiptSignature.ServiceRecords), "serviceRecord") + .Add(Restrictions.In("serviceRecord.Oid", serviceRecordOids.ToList())); + + var hasSignatures = criteria.List().Any(); + + return hasSignatures; + } + + public List LoadConfirmationReceiptSignaturesByServiceRecordOids(IList serviceRecordOids) + { var c = CreateCriteriaIsActive() .CreateAlias(nameof(ConfirmationReceiptSignature.ServiceRecords), "sr", JoinType.InnerJoin) - .Add(Restrictions.In(nameof(BeWoEntityBase.Oid), serviceRecordOids.ToArray())); + .Add(Restrictions.In($"sr.{nameof(BeWoEntityBase.Oid)}", serviceRecordOids.ToArray())); - var kek = c.List().ToList(); + // Der ResultTransformer erzeugt ein SELECT DISTINCT für den Roottypen (ConfirmationReceiptSignature) + c.SetResultTransformer(new DistinctRootEntityResultTransformer()); - if(serviceRecordOids.Any()) + var result = c.List().ToList(); + + return result; + } + + public List LoadServiceRecordOidsWithConfirmationReceiptSignatures(IList serviceRecordOids) + { + var c = CreateCriteriaIsActive() + .CreateAlias(nameof(ConfirmationReceiptSignature.ServiceRecords), "sr", JoinType.InnerJoin) + .Add(Restrictions.In($"sr.{nameof(BeWoEntityBase.Oid)}", serviceRecordOids.ToArray())); + + // Der ResultTransformer erzeugt ein SELECT DISTINCT für den Roottypen (ConfirmationReceiptSignature) + c.SetResultTransformer(new DistinctRootEntityResultTransformer()); + + var confirmationReceiptSignatures = c.List().ToList(); + + var result = new List(); + + confirmationReceiptSignatures.DoForEach(crs => crs.ServiceRecords.DoForEach(sr => { + if(sr.Oid.HasValue) + { + result.AddIfNotIn(sr.Oid.Value); + } + })); - } + return result; + } - return false;//criteria.List().Any(); + public List LoadServiceRecordOidsWithConfirmationReceiptSignatures(IList serviceRecordOids, SignatureType signatureType) + { + var c = CreateCriteriaIsActive() + .Add(Restrictions.Eq(nameof(ConfirmationReceiptSignature.SignatureType), signatureType)) + .CreateAlias(nameof(ConfirmationReceiptSignature.ServiceRecords), "sr", JoinType.InnerJoin) + .Add(Restrictions.In($"sr.{nameof(BeWoEntityBase.Oid)}", serviceRecordOids.ToArray())); + + // Der ResultTransformer erzeugt ein SELECT DISTINCT für den Roottypen (ConfirmationReceiptSignature) + c.SetResultTransformer(new DistinctRootEntityResultTransformer()); + + var confirmationReceiptSignatures = c.List().ToList(); + + var result = new List(); + + confirmationReceiptSignatures.DoForEach(crs => crs.ServiceRecords.DoForEach(sr => + { + if(sr.Oid.HasValue) + { + result.AddIfNotIn(sr.Oid.Value); + } + })); + + return result; + } + + public IEnumerable GetServiceRecordsWithoutConfirmationReceiptSignature(IList serviceRecordOids, SignatureType signatureType) + { + var c = CreateCriteriaIsActive() + .Add(Restrictions.Eq(nameof(ConfirmationReceiptSignature.SignatureType), signatureType)) + .CreateAlias(nameof(ConfirmationReceiptSignature.ServiceRecords), "sr", JoinType.InnerJoin) + .Add(Restrictions.In($"sr.{nameof(BeWoEntityBase.Oid)}", serviceRecordOids.ToArray())) + .SetResultTransformer(new DistinctRootEntityResultTransformer()); + + var confirmationReceiptSignatures = c.List().ToList(); + + var serviceRecords = new List(); + + confirmationReceiptSignatures.DoForEach(crs => serviceRecords.AddRangeIfElementsNotIn(crs.ServiceRecords)); + + return serviceRecords; } } } diff --git a/Data/Entities/ConfirmationReceiptSignature.cs b/Data/Entities/ConfirmationReceiptSignature.cs index 102810e5c..a9dfcd50d 100644 --- a/Data/Entities/ConfirmationReceiptSignature.cs +++ b/Data/Entities/ConfirmationReceiptSignature.cs @@ -5,21 +5,39 @@ namespace BeWo.Data.Entities { public class ConfirmationReceiptSignature : BeWoEntityBase { - private long? _EmployeeOid; + private long? _CustomerOid; + + private Employee _Employee; private IList _ServiceRecords; private string _SignatureImage; - public virtual long? EmployeeOid + private string _TimeSpanString; + + + public virtual Employee Employee { - get => _EmployeeOid; + get => _Employee; set { - if(AreDifferent(_EmployeeOid, value)) + if(AreDifferent(_Employee, value)) { - _EmployeeOid = value; + _Employee = value; + } + } + } + + public virtual long? CustomerOid + { + get => _CustomerOid; + + set + { + if(AreDifferent(_CustomerOid, value)) + { + _CustomerOid = value; } } } @@ -55,5 +73,32 @@ namespace BeWo.Data.Entities _Tid = TableID.ConfirmationReceiptSignature; } + private SignatureType _SignatureType; + + public virtual SignatureType SignatureType + { + get => _SignatureType; + + set + { + if(AreDifferent(_SignatureType, value)) + { + _SignatureType = value; + } + } + } + + public virtual string TimeSpanString + { + get => _TimeSpanString; + + set + { + if(AreDifferent(_TimeSpanString, value)) + { + _TimeSpanString = value; + } + } + } } } diff --git a/Data/Mappings/ConfirmationReceiptSignature.hbm.xml b/Data/Mappings/ConfirmationReceiptSignature.hbm.xml index 2c5a6bc45..192a2d595 100644 --- a/Data/Mappings/ConfirmationReceiptSignature.hbm.xml +++ b/Data/Mappings/ConfirmationReceiptSignature.hbm.xml @@ -13,10 +13,14 @@ - - + + + + - + + + diff --git a/Model/Changes_2021_01_20_SignatureType_ConfirmationReceiptSignature.txt b/Model/Changes_2021_01_20_SignatureType_ConfirmationReceiptSignature.txt new file mode 100644 index 000000000..76be0a948 --- /dev/null +++ b/Model/Changes_2021_01_20_SignatureType_ConfirmationReceiptSignature.txt @@ -0,0 +1 @@ +ALTER TABLE confirmationreceiptsignature ADD COLUMN `SignatureType` tinyint(4); \ No newline at end of file diff --git a/Model/Changes_2021_02_02_CustomerOid zu ConfirmationReceiptSignature.txt b/Model/Changes_2021_02_02_CustomerOid zu ConfirmationReceiptSignature.txt new file mode 100644 index 000000000..46ae96a91 --- /dev/null +++ b/Model/Changes_2021_02_02_CustomerOid zu ConfirmationReceiptSignature.txt @@ -0,0 +1,3 @@ +ALTER TABLE confirmationreceiptsignature ADD COLUMN CustomerOid BIGINT(19); +ALTER TABLE confirmationreceiptsignature ADD KEY CONFIRMATIONRECEIPTSIGNATURE_CUSTOMER_FK (CustomerOid); +ALTER TABLE confirmationreceiptsignature ADD CONSTRAINT FK_CONFIRMATIONRECEIPTSIGNATURE2CUSTOMER FOREIGN KEY (CustomerOid) REFERENCES Customer(Oid); \ No newline at end of file diff --git a/Report/DefaultReports/Quittierungsbeleg.Designer.cs b/Report/DefaultReports/Quittierungsbeleg.Designer.cs index 4c74cfc31..fffd71c15 100644 --- a/Report/DefaultReports/Quittierungsbeleg.Designer.cs +++ b/Report/DefaultReports/Quittierungsbeleg.Designer.cs @@ -113,8 +113,12 @@ namespace BeWo.Report.DefaultReports this.xrLabel10 = new DevExpress.XtraReports.UI.XRLabel(); this.xrLabel9 = new DevExpress.XtraReports.UI.XRLabel(); this.xrLabel1 = new DevExpress.XtraReports.UI.XRLabel(); + this.xrPictureBox1 = new DevExpress.XtraReports.UI.XRPictureBox(); + this.xrLabel17 = new DevExpress.XtraReports.UI.XRLabel(); this.fieldKontaktArt = new DevExpress.XtraReports.UI.CalculatedField(); this.bindingSource1 = new System.Windows.Forms.BindingSource(this.components); + this.xrLabel18 = new DevExpress.XtraReports.UI.XRLabel(); + this.xrPictureBox2 = new DevExpress.XtraReports.UI.XRPictureBox(); ((System.ComponentModel.ISupportInitialize)(this.xrTable3)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.xrTableServiceRecords1)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.xrTableAbwesenheiten)).BeginInit(); @@ -292,7 +296,7 @@ namespace BeWo.Report.DefaultReports this.picSignature.Borders = DevExpress.XtraPrinting.BorderSide.None; this.picSignature.DataBindings.AddRange(new DevExpress.XtraReports.UI.XRBinding[] { new DevExpress.XtraReports.UI.XRBinding("Tag", null, "Services.Signature")}); - this.picSignature.LocationFloat = new DevExpress.Utils.PointFloat(1F, 1F); + this.picSignature.LocationFloat = new DevExpress.Utils.PointFloat(0F, 0F); this.picSignature.Name = "picSignature"; this.picSignature.SizeF = new System.Drawing.SizeF(158F, 18F); this.picSignature.Sizing = DevExpress.XtraPrinting.ImageSizeMode.ZoomImage; @@ -645,10 +649,10 @@ namespace BeWo.Report.DefaultReports // this.xrLabel5.Borders = ((DevExpress.XtraPrinting.BorderSide)((DevExpress.XtraPrinting.BorderSide.Top | DevExpress.XtraPrinting.BorderSide.Right))); this.xrLabel5.Font = new System.Drawing.Font("Arial", 10F); - this.xrLabel5.LocationFloat = new DevExpress.Utils.PointFloat(170F, 47.11109F); + this.xrLabel5.LocationFloat = new DevExpress.Utils.PointFloat(170F, 47.1111F); this.xrLabel5.Name = "xrLabel5"; this.xrLabel5.Padding = new DevExpress.XtraPrinting.PaddingInfo(3, 2, 0, 0, 100F); - this.xrLabel5.SizeF = new System.Drawing.SizeF(158.3612F, 30.50001F); + this.xrLabel5.SizeF = new System.Drawing.SizeF(209.3611F, 30.50001F); this.xrLabel5.StylePriority.UseBackColor = false; this.xrLabel5.StylePriority.UseBorders = false; this.xrLabel5.StylePriority.UseFont = false; @@ -697,12 +701,14 @@ namespace BeWo.Report.DefaultReports // xrLabel2 // this.xrLabel2.Font = new System.Drawing.Font("Arial", 14F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.xrLabel2.ForeColor = System.Drawing.Color.Black; this.xrLabel2.LocationFloat = new DevExpress.Utils.PointFloat(0F, 0F); this.xrLabel2.Multiline = true; this.xrLabel2.Name = "xrLabel2"; this.xrLabel2.Padding = new DevExpress.XtraPrinting.PaddingInfo(2, 2, 0, 0, 100F); this.xrLabel2.SizeF = new System.Drawing.SizeF(674.9998F, 25F); this.xrLabel2.StylePriority.UseFont = false; + this.xrLabel2.StylePriority.UseForeColor = false; this.xrLabel2.StylePriority.UseTextAlignment = false; this.xrLabel2.Text = "Quittierungsbeleg [Mandator.Name]"; this.xrLabel2.TextAlignment = DevExpress.XtraPrinting.TextAlignment.TopCenter; @@ -741,6 +747,8 @@ namespace BeWo.Report.DefaultReports // GroupFooter1 // this.GroupFooter1.Controls.AddRange(new DevExpress.XtraReports.UI.XRControl[] { + this.xrLabel18, + this.xrPictureBox2, this.lblUnterschriftKlient, this.lblUnterschriftMitarbeiter, this.xrTableAbwesenheiten, @@ -754,7 +762,9 @@ namespace BeWo.Report.DefaultReports this.xrLabel11, this.xrLabel10, this.xrLabel9, - this.xrLabel1}); + this.xrLabel1, + this.xrPictureBox1, + this.xrLabel17}); this.GroupFooter1.HeightF = 270F; this.GroupFooter1.KeepTogether = true; this.GroupFooter1.Name = "GroupFooter1"; @@ -1165,6 +1175,26 @@ namespace BeWo.Report.DefaultReports this.xrLabel1.StylePriority.UseTextAlignment = false; this.xrLabel1.TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleCenter; // + // xrPictureBox1 + // + this.xrPictureBox1.DataBindings.AddRange(new DevExpress.XtraReports.UI.XRBinding[] { + new DevExpress.XtraReports.UI.XRBinding("Tag", null, "EmployeeSignature")}); + this.xrPictureBox1.LocationFloat = new DevExpress.Utils.PointFloat(535.6389F, 227F); + this.xrPictureBox1.Name = "xrPictureBox1"; + this.xrPictureBox1.Scripts.OnBeforePrint = "xrPictureBox1_BeforePrint"; + this.xrPictureBox1.SizeF = new System.Drawing.SizeF(100F, 23F); + this.xrPictureBox1.Sizing = DevExpress.XtraPrinting.ImageSizeMode.ZoomImage; + this.xrPictureBox1.BeforePrint += new System.Drawing.Printing.PrintEventHandler(this.EmployeeSignature_BeforePrint); + // + // xrLabel17 + // + this.xrLabel17.DataBindings.AddRange(new DevExpress.XtraReports.UI.XRBinding[] { + new DevExpress.XtraReports.UI.XRBinding("Text", null, "EmployeeSignatureDate", "{0:dd.MM.yyyy,}")}); + this.xrLabel17.LocationFloat = new DevExpress.Utils.PointFloat(435.1388F, 227F); + this.xrLabel17.Name = "xrLabel17"; + this.xrLabel17.Padding = new DevExpress.XtraPrinting.PaddingInfo(2, 2, 0, 0, 100F); + this.xrLabel17.SizeF = new System.Drawing.SizeF(100F, 23F); + // // fieldKontaktArt // this.fieldKontaktArt.DataMember = "Services"; @@ -1176,6 +1206,25 @@ namespace BeWo.Report.DefaultReports // this.bindingSource1.DataSource = typeof(BeWo.Report.ReportObjects.ServicesOverviewRO); // + // xrLabel18 + // + this.xrLabel18.DataBindings.AddRange(new DevExpress.XtraReports.UI.XRBinding[] { + new DevExpress.XtraReports.UI.XRBinding("Text", null, "CustomerSignatureDate", "{0:dd.MM.yyyy,}")}); + this.xrLabel18.LocationFloat = new DevExpress.Utils.PointFloat(129.4998F, 227F); + this.xrLabel18.Name = "xrLabel18"; + this.xrLabel18.Padding = new DevExpress.XtraPrinting.PaddingInfo(2, 2, 0, 0, 100F); + this.xrLabel18.SizeF = new System.Drawing.SizeF(100F, 23F); + // + // xrPictureBox2 + // + this.xrPictureBox2.DataBindings.AddRange(new DevExpress.XtraReports.UI.XRBinding[] { + new DevExpress.XtraReports.UI.XRBinding("Tag", null, "CustomerSignature")}); + this.xrPictureBox2.LocationFloat = new DevExpress.Utils.PointFloat(230F, 227F); + this.xrPictureBox2.Name = "xrPictureBox2"; + this.xrPictureBox2.SizeF = new System.Drawing.SizeF(100F, 23F); + this.xrPictureBox2.Sizing = DevExpress.XtraPrinting.ImageSizeMode.ZoomImage; + this.xrPictureBox2.BeforePrint += new System.Drawing.Printing.PrintEventHandler(this.CustomerSignature_BeforePrint); + // // Quittierungsbeleg // this.Bands.AddRange(new DevExpress.XtraReports.UI.Band[] { @@ -1295,5 +1344,9 @@ namespace BeWo.Report.DefaultReports private DevExpress.XtraReports.UI.XRLabel xrLabel14; private DevExpress.XtraReports.UI.XRLabel xrLabel16; private DevExpress.XtraReports.UI.XRPictureBox picSignature; + private DevExpress.XtraReports.UI.XRPictureBox xrPictureBox1; + private DevExpress.XtraReports.UI.XRLabel xrLabel17; + private DevExpress.XtraReports.UI.XRLabel xrLabel18; + private DevExpress.XtraReports.UI.XRPictureBox xrPictureBox2; } } diff --git a/Report/DefaultReports/Quittierungsbeleg.cs b/Report/DefaultReports/Quittierungsbeleg.cs index a0b8e4df6..6409857b4 100644 --- a/Report/DefaultReports/Quittierungsbeleg.cs +++ b/Report/DefaultReports/Quittierungsbeleg.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Drawing; using System.IO; using System.Text.RegularExpressions; @@ -10,7 +9,7 @@ using DevExpress.XtraReports.UI; namespace BeWo.Report.DefaultReports { - public partial class Quittierungsbeleg : DevExpress.XtraReports.UI.XtraReport, IBeWoReport + public partial class Quittierungsbeleg : XtraReport, IBeWoReport { public Quittierungsbeleg() { @@ -19,10 +18,6 @@ namespace BeWo.Report.DefaultReports public void SetReportDataSource(ServicesOverviewRO pRO) { - StackTrace stackTrace = new StackTrace(); - // Get calling method name - Debug.WriteLine(stackTrace.GetFrame(1).GetMethod().Name); - bool hatGruppen = false; //if (pRO == null) @@ -127,13 +122,54 @@ namespace BeWo.Report.DefaultReports } } + private void EmployeeSignature_BeforePrint(object sender, System.Drawing.Printing.PrintEventArgs e) + { + if(sender is XRPictureBox pictureBox) + { + var base64String = pictureBox.Tag as string; + + if(!string.IsNullOrWhiteSpace(base64String)) + { + var base64Data = Regex.Match(base64String, @"data:image/(?.+?),(?.+)").Groups["data"].Value; + var binaryData = Convert.FromBase64String(base64Data); + var image = ByteArrayToImage(binaryData); + + pictureBox.Image = image; + } + else + { + pictureBox.Image = null; + } + } + } + + private void CustomerSignature_BeforePrint(object sender, System.Drawing.Printing.PrintEventArgs e) + { + if(sender is XRPictureBox pictureBox) + { + var base64String = pictureBox.Tag as string; + + if(!string.IsNullOrWhiteSpace(base64String)) + { + var base64Data = Regex.Match(base64String, @"data:image/(?.+?),(?.+)").Groups["data"].Value; + var binaryData = Convert.FromBase64String(base64Data); + var image = ByteArrayToImage(binaryData); + + pictureBox.Image = image; + } + else + { + pictureBox.Image = null; + } + } + } + public Image ByteArrayToImage(byte[] byteArrayIn) { - Image returnImage = null; - MemoryStream ms = new System.IO.MemoryStream(byteArrayIn); - returnImage = Image.FromStream(ms); - - return returnImage; + using(var memoryStream = new MemoryStream(byteArrayIn)) + { + return Image.FromStream(memoryStream); + } } } } diff --git a/Report/ReportObjects/ServicesOverviewRO.cs b/Report/ReportObjects/ServicesOverviewRO.cs index 729260abc..8fac9f6ea 100644 --- a/Report/ReportObjects/ServicesOverviewRO.cs +++ b/Report/ReportObjects/ServicesOverviewRO.cs @@ -171,6 +171,12 @@ namespace BeWo.Report.ReportObjects public string TotalGefahreneKilometerString { get; set; } + public string EmployeeSignature { get; set; } + public DateTime? EmployeeSignatureDate { get; set; } + + public string CustomerSignature { get; set; } + public DateTime? CustomerSignatureDate { get; set; } + public int Year { get; set; } public IList CostBearer2SupportConceptList { get; set; } @@ -1357,6 +1363,23 @@ namespace BeWo.Report.ReportObjects lResult.SupportConceptCostBearer = cb2scs.Values.First(); } + var mandatorSettings = lResult.Mandator?.Settings; + + if(mandatorSettings.Contains("ShowEmployeeSignature=1")) + { + var serviceRecordOids = lResult.Services.Select(service => service.ServiceRecordOid).ToList(); + + var employeeSignature = DAOFactory.SearchDAO.GetConfirmationReceiptSignatureForServiceRecords(serviceRecordOids, SignatureType.Employee); + + lResult.EmployeeSignature = employeeSignature?.SignatureImage; + lResult.EmployeeSignatureDate = employeeSignature?.InsTs; + + var customerSignature = DAOFactory.SearchDAO.GetConfirmationReceiptSignatureForServiceRecords(serviceRecordOids, SignatureType.Customer); + + lResult.CustomerSignature = customerSignature?.SignatureImage; + lResult.CustomerSignatureDate = customerSignature?.InsTs; + } + return lResult; } diff --git a/Service/DCEntityMapper/ConfirmationReceiptSignatureDC_ConfirmationReceiptSignature.cs b/Service/DCEntityMapper/ConfirmationReceiptSignatureDC_ConfirmationReceiptSignature.cs index bf18daa2b..103a944ae 100644 --- a/Service/DCEntityMapper/ConfirmationReceiptSignatureDC_ConfirmationReceiptSignature.cs +++ b/Service/DCEntityMapper/ConfirmationReceiptSignatureDC_ConfirmationReceiptSignature.cs @@ -12,10 +12,20 @@ namespace BeWo.Service.DCEntityMapper pDataContract.ConfirmationReceiptSignatureOid = pEntity.Oid; pDataContract.ConfirmationReceiptSignatureVersion = pEntity.Version; pDataContract.SignatureImage = pEntity.SignatureImage; - pDataContract.EmployeeOid = pEntity.EmployeeOid; + + pDataContract.CustomerOid = pEntity.CustomerOid; + + pDataContract.SignatureType = pEntity.SignatureType; + + pDataContract.TimeSpanString = pEntity.TimeSpanString; pDataContract.ServiceRecords = MapperFactory.ServiceRecordDC_ServiceRecord.MapToNewDCs(pEntity.ServiceRecords); + if(pEntity.Employee != null) + { + pDataContract.Employee = MapperFactory.CompactEmployeeDC_Employee.MapToNewDC(pEntity.Employee); + } + return pDataContract; } @@ -26,13 +36,23 @@ namespace BeWo.Service.DCEntityMapper pEntity.Oid = pDataContract.ConfirmationReceiptSignatureOid; pEntity.Version = pDataContract.ConfirmationReceiptSignatureVersion; pEntity.SignatureImage = pDataContract.SignatureImage; - pEntity.EmployeeOid = pDataContract.EmployeeOid; + + pEntity.CustomerOid = pDataContract.CustomerOid; + + pEntity.SignatureType = pDataContract.SignatureType; + + pEntity.TimeSpanString = pDataContract.TimeSpanString; if(pDataContract.ServiceRecords != null) { pEntity.ServiceRecords = DAOFactory.GenericDAO.LoadByIDs(pDataContract.ServiceRecords.Select(s => s.ServiceRecordOid.Value)); } + if(pDataContract.Employee != null) + { + pEntity.Employee = DAOFactory.GenericDAO.LoadByID(pDataContract.Employee.EmployeeOid); + } + return pEntity; } diff --git a/Service/OwnChat/OwnChatHelper.cs b/Service/OwnChat/OwnChatHelper.cs index d1f29e26c..b471f286d 100644 --- a/Service/OwnChat/OwnChatHelper.cs +++ b/Service/OwnChat/OwnChatHelper.cs @@ -1,10 +1,6 @@ using System; -using System.Collections.Generic; using System.IO; -using System.Linq; using System.Net; -using System.Text; -using System.Threading.Tasks; using BeWo.Service.Configuration; using BeWo.Service.Core; using BeWo.Service.Plugins; diff --git a/Service/ServiceContracts/IEmployeeService.cs b/Service/ServiceContracts/IEmployeeService.cs index 86fe0aca4..a15102123 100644 --- a/Service/ServiceContracts/IEmployeeService.cs +++ b/Service/ServiceContracts/IEmployeeService.cs @@ -403,5 +403,9 @@ namespace BeWo.Service.ServiceContracts [FaultContract(typeof(BeWoFault))] [OperationContract] List GetActiveSupportConceptsForEmployee(long? employeeOid, CustomerFilterEnum supportConceptFilter); + + [FaultContract(typeof(BeWoFault))] + [OperationContract] + List FindTeamCustomers(long? teamOid); } } \ No newline at end of file diff --git a/Service/ServiceContracts/IOperationsService.cs b/Service/ServiceContracts/IOperationsService.cs index 87d3ce9ba..c3cdf93e6 100644 --- a/Service/ServiceContracts/IOperationsService.cs +++ b/Service/ServiceContracts/IOperationsService.cs @@ -974,7 +974,7 @@ namespace BeWo.Service.ServiceContracts [FaultContract(typeof(BeWoFault))] [OperationContract] - bool HasConfirmationReceiptSignatureByDateAndCustomer(long customerOid, DateTimeSpan timeSpan); + bool HasConfirmationReceiptSignatureByDateAndCustomer(long customerOid, DateTimeSpan timeSpan, SignatureType signatureType); [FaultContract(typeof(BeWoFault))] [OperationContract] @@ -1026,7 +1026,7 @@ namespace BeWo.Service.ServiceContracts [FaultContract(typeof(BeWoFault))] [OperationContract] - bool HasConfirmationReceiptSignature(IEnumerable customerOids, long? employeeOid, long? costbearerOid, long? serviceCategoryOid, DateTimeSpan timeSpan); + bool HasConfirmationReceiptSignature(IList serviceRecordOids, SignatureType signatureType); [FaultContract(typeof(BeWoFault))] [OperationContract] @@ -1044,5 +1044,37 @@ namespace BeWo.Service.ServiceContracts [FaultContract(typeof(BeWoFault))] [OperationContract] string GetObjectForFilePath(TableID table, long? oid); + + [FaultContract(typeof(BeWoFault))] + [OperationContract] + List LoadConfirmationReceiptSignaturesByServiceRecordOids(IList serviceRecordOids, SignatureType signatureType, out List serviceRecordOidsWithSignatures); + + [FaultContract(typeof(BeWoFault))] + [OperationContract] + List UpdateConfirmationReceiptSignatures(IList confirmationReceiptSignatures2Update); + + [FaultContract(typeof(BeWoFault))] + [OperationContract] + void DeleteConfirmationReceiptSignatures(Dictionary oid2Version); + + [FaultContract(typeof(BeWoFault))] + [OperationContract] + bool HasConfirmationReceiptSignaturesByCustomerAndServiceRecords(long customerOid, IEnumerable serviceRecordOids); + + [FaultContract(typeof(BeWoFault))] + [OperationContract] + List LoadAllConfirmationReceiptSignaturesByServiceRecordOids(IList serviceRecordOids, out Dictionary> serviceRecordOidsWithSignature); + + [FaultContract(typeof(BeWoFault))] + [OperationContract] + List LoadServiceRecordOidsWithConfirmationReceiptSignatures(IList serviceRecordOids); + + [FaultContract(typeof(BeWoFault))] + [OperationContract] + List LoadServiceRecordOidsWithCustomerConfirmationReceiptSignatures(IList serviceRecordOids, SignatureType signatureType); + + [FaultContract(typeof(BeWoFault))] + [OperationContract] + List GetServiceRecordsWithoutConfirmationReceiptSignature(IList serviceRecordOids, SignatureType signatureType); } } \ No newline at end of file diff --git a/Service/ServiceImplementations/EmployeeServiceImp.cs b/Service/ServiceImplementations/EmployeeServiceImp.cs index 644a202a1..fe786bc41 100644 --- a/Service/ServiceImplementations/EmployeeServiceImp.cs +++ b/Service/ServiceImplementations/EmployeeServiceImp.cs @@ -1684,6 +1684,8 @@ namespace BeWo.Service.ServiceImplementations var teams = new List(); + var teamOids = teams.Where(team => team.Oid.HasValue).Select(team => team.Oid.Value); + if(teamOid.HasValue) { teams.Add(DAOFactory.GenericDAO.LoadByID(teamOid.Value)); @@ -1694,25 +1696,20 @@ namespace BeWo.Service.ServiceImplementations teams.AddRange(DAOFactory.SearchDAO.FindTeamsOfEmployee(employeeOid)); } - foreach(var team in teams) + teams.DoForEach(team => { - foreach(var employee in team.MemberList) + team.MemberList.Where(member => member.Oid.HasValue && member.Oid != employeeOid).DoForEach(member => { - foreach(var employee2Customer in employee.Employee2CustomerList) - { - if(employee2Customer.Customer.IsActive == ActivationTypeId.Active) - { - foreach(var valueListEntry2Object in employee2Customer.ValueList) - { - if(valueListEntry2Object.Entry.Type == ValueListEntryType.StaffRoleType && valueListEntry2Object.SystemEntryID == SystemEntryID.EmployeeRoleMainAttendant && employee2Customer.Customer?.Oid != null) - { - result.AddIfNotIn(employee2Customer.Customer.Oid.Value); - } - } - } - } - } - } + // Nur, wo der Klient auch vom Team betreut wird + result.AddRangeIfElementsNotIn( + member.Employee2CustomerList.Where( + employee2Customer => employee2Customer.CustomerOid.HasValue && + employee2Customer.Customer.Team2CustomerList.Any(team2Customer => team2Customer.TeamOid.HasValue && + teamOids.Contains(team2Customer.TeamOid.Value)) + ).Select(employee2Customer => employee2Customer.CustomerOid.Value) + ); + }); + }); return result; } @@ -1773,5 +1770,67 @@ namespace BeWo.Service.ServiceImplementations throw Utils.CreateBeWoFaultException(exception); } } + + public List FindTeamCustomers(long? teamOid) + { + try + { + var customerOids = new List(); + + ApplicationUser loggedInUser; + + if(LoggedInUserOperationContextExt.Current != null && LoggedInUserOperationContextExt.Current.User != null) + { + loggedInUser = LoggedInUserOperationContextExt.Current.User; + } + else + { + loggedInUser = SessionFacade.LoggedInUser; + } + + if(loggedInUser?.Employee != null) + { + var teams = new List(); + + if(teamOid.HasValue) + { + teams.Add(DAOFactory.GenericDAO.LoadByID(teamOid.Value)); + } + else if(loggedInUser.Employee.Oid.HasValue) + { + teams.AddRange(DAOFactory.SearchDAO.FindLeadingTeams(loggedInUser.Employee.Oid.Value)); + teams.AddRange(DAOFactory.SearchDAO.FindTeamsOfEmployee(loggedInUser.Employee.Oid.Value)); + } + + foreach(var team in teams) + { + if(!team.Oid.HasValue) + { + continue; + } + + var customers = DAOFactory.SearchDAO.FindCustomerOfTeam(team.Oid.Value); + foreach(var c in customers) + { + if(c.IsActive == ActivationTypeId.Active) + { + if(c.Oid.HasValue && !customerOids.Contains(c.Oid.Value)) + { + customerOids.Add(c.Oid.Value); + } + } + + } + + } + } + + return customerOids; + } + catch(Exception exception) + { + throw Utils.CreateBeWoFaultException(exception); + } + } } } \ No newline at end of file diff --git a/Service/ServiceImplementations/OperationsServiceImp.cs b/Service/ServiceImplementations/OperationsServiceImp.cs index 974f392a9..f1c5bded8 100644 --- a/Service/ServiceImplementations/OperationsServiceImp.cs +++ b/Service/ServiceImplementations/OperationsServiceImp.cs @@ -6522,11 +6522,11 @@ namespace BeWo.Service.ServiceImplementations } } - public bool HasConfirmationReceiptSignatureByDateAndCustomer(long customerOid, DateTimeSpan timeSpan) + public bool HasConfirmationReceiptSignatureByDateAndCustomer(long customerOid, DateTimeSpan timeSpan, SignatureType signatureType) { try { - return DAOFactory.SearchDAO.HasConfirmationReceiptSignatureByDateAndCustomer(customerOid, timeSpan); + return DAOFactory.SearchDAO.HasConfirmationReceiptSignatureByDateAndCustomer(customerOid, timeSpan, signatureType); } catch (Exception exception) { @@ -6910,11 +6910,11 @@ namespace BeWo.Service.ServiceImplementations } } - public bool HasConfirmationReceiptSignature(IEnumerable customerOids, long? employeeOid, long? costbearerOid, long? serviceCategoryOid, DateTimeSpan timeSpan) + public bool HasConfirmationReceiptSignature(IList serviceRecordOids, SignatureType signatureType) { try { - return DAOFactory.SearchDAO.HasConfirmationReceiptSignature(customerOids, employeeOid, costbearerOid, serviceCategoryOid, timeSpan); + return DAOFactory.SearchDAO.HasConfirmationReceiptSignature(serviceRecordOids, signatureType); } catch(Exception e) { @@ -7766,5 +7766,136 @@ namespace BeWo.Service.ServiceImplementations return span; } + + public List LoadConfirmationReceiptSignaturesByServiceRecordOids(IList serviceRecordOids, SignatureType signatureType, out List serviceRecordOidsWithSignatures) + { + try + { + var signatures = DAOFactory.SearchDAO.LoadConfirmationReceiptSignaturesByServiceRecordOids(serviceRecordOids, signatureType); + + serviceRecordOidsWithSignatures = new List(); + + foreach(var crs in signatures) + { + foreach(var sr in crs.ServiceRecords) + { + if(sr.Oid.HasValue && serviceRecordOids.Contains(sr.Oid.Value)) + { + serviceRecordOidsWithSignatures.AddIfNotIn(sr.Oid.Value); + } + } + } + + return MapperFactory.ConfirmationReceiptSignatureDC_ConfirmationReceiptSignature.MapToNewDCs(signatures); + } + catch(Exception e) + { + throw Utils.CreateBeWoFaultException(e); + } + } + + public List UpdateConfirmationReceiptSignatures(IList confirmationReceiptSignatures2Update) + { + try + { + var lOriginals = DAOFactory.GenericDAO.LoadByIDs(confirmationReceiptSignatures2Update.Where(w => w.ConfirmationReceiptSignatureOid.HasValue).Select(confirmationReceiptSignatur => confirmationReceiptSignatur.ConfirmationReceiptSignatureOid.Value)); + + MapperFactory.ConfirmationReceiptSignatureDC_ConfirmationReceiptSignature.MergeWithEntitys(confirmationReceiptSignatures2Update, lOriginals); + + DAOFactory.GenericDAO.Update(lOriginals); + + lOriginals = DAOFactory.GenericDAO.LoadByIDs(confirmationReceiptSignatures2Update.Where(w => w.ConfirmationReceiptSignatureOid.HasValue).Select(confirmationReceiptSignatur => confirmationReceiptSignatur.ConfirmationReceiptSignatureOid.Value)); + + return MapperFactory.ConfirmationReceiptSignatureDC_ConfirmationReceiptSignature.MapToNewDCs(lOriginals); + } + catch(Exception e) + { + throw Utils.CreateBeWoFaultException(e); + } + } + + public void DeleteConfirmationReceiptSignatures(Dictionary oid2Version) + { + try + { + var originals = DAOFactory.GenericDAO.LoadByIDs(oid2Version.Select(e => e.Key)); + originals.DoForEach(or => MapperFactory.ConfirmationReceiptSignatureDC_ConfirmationReceiptSignature.ConcurrencyCheck(oid2Version[or.Oid.Value], or)); + + DAOFactory.GenericDAO.Delete(originals); + } + catch(Exception e) + { + throw Utils.CreateBeWoFaultException(e); + } + } + + public bool HasConfirmationReceiptSignaturesByCustomerAndServiceRecords(long customerOid, IEnumerable serviceRecordOids) + { + try + { + return DAOFactory.SearchDAO.HasConfirmationReceiptSignaturesByCustomerAndServiceRecords(customerOid, serviceRecordOids); + } + catch(Exception exception) + { + throw Utils.CreateBeWoFaultException(exception); + } + } + + public List LoadAllConfirmationReceiptSignaturesByServiceRecordOids(IList serviceRecordOids, out Dictionary> serviceRecordOidsWithSignature) + { + try + { + var confirmationReceiptSignatures = DAOFactory.SearchDAO.LoadConfirmationReceiptSignaturesByServiceRecordOids(serviceRecordOids); + + serviceRecordOidsWithSignature = new Dictionary>(); + + foreach(var csr in confirmationReceiptSignatures) + { + serviceRecordOidsWithSignature.AddOrUpdateValueInDictionary(csr.SignatureType, csr.ServiceRecords.Where(sr => sr.Oid.HasValue).Select(sr => sr.Oid.Value).ToList()); + } + + return MapperFactory.ConfirmationReceiptSignatureDC_ConfirmationReceiptSignature.MapToNewDCs(confirmationReceiptSignatures); + } + catch(Exception exception) + { + throw Utils.CreateBeWoFaultException(exception); + } + } + + public List LoadServiceRecordOidsWithConfirmationReceiptSignatures(IList serviceRecordOids) + { + try + { + return DAOFactory.SearchDAO.LoadServiceRecordOidsWithConfirmationReceiptSignatures(serviceRecordOids); + } + catch(Exception exception) + { + throw Utils.CreateBeWoFaultException(exception); + } + } + + public List LoadServiceRecordOidsWithCustomerConfirmationReceiptSignatures(IList serviceRecordOids, SignatureType signatureType) + { + try + { + return DAOFactory.SearchDAO.LoadServiceRecordOidsWithConfirmationReceiptSignatures(serviceRecordOids, signatureType); + } + catch(Exception exception) + { + throw Utils.CreateBeWoFaultException(exception); + } + } + + public List GetServiceRecordsWithoutConfirmationReceiptSignature(IList serviceRecordOids, SignatureType signatureType) + { + try + { + return MapperFactory.ServiceRecordDC_ServiceRecord.MapToNewDCs(DAOFactory.SearchDAO.GetServiceRecordsWithoutConfirmationReceiptSignature(serviceRecordOids, signatureType)); + } + catch(Exception exception) + { + throw Utils.CreateBeWoFaultException(exception); + } + } } } diff --git a/Shared/BeWoEntityEnums.cs b/Shared/BeWoEntityEnums.cs index 5eed4d7fd..7c82aaa43 100644 --- a/Shared/BeWoEntityEnums.cs +++ b/Shared/BeWoEntityEnums.cs @@ -1107,4 +1107,9 @@ namespace BS.Shared Ort } + public enum SignatureType + { + Employee, + Customer + } } \ No newline at end of file diff --git a/Shared/DataContracts/ClientPartials/CostRatePeriodDC.cs b/Shared/DataContracts/ClientPartials/CostRatePeriodDC.cs index 2c3c61e8b..3e8e2daed 100644 --- a/Shared/DataContracts/ClientPartials/CostRatePeriodDC.cs +++ b/Shared/DataContracts/ClientPartials/CostRatePeriodDC.cs @@ -4,17 +4,16 @@ { public override bool Equals(object obj) { - if (obj is CostRatePeriodDC) + if (obj is CostRatePeriodDC costRatePeriod) { - var y = (CostRatePeriodDC)obj; - if (this.CostRatePeriodOid == null && y.CostRatePeriodOid == null) + if (CostRatePeriodOid == null && costRatePeriod.CostRatePeriodOid == null) { - return this.GetHashCode() == y.GetHashCode(); + return GetHashCode() == costRatePeriod.GetHashCode(); } - if (this.CostRatePeriodOid != null && y.CostRatePeriodOid != null) + if (CostRatePeriodOid != null && costRatePeriod.CostRatePeriodOid != null) { - return this.CostRatePeriodOid == y.CostRatePeriodOid; + return CostRatePeriodOid == costRatePeriod.CostRatePeriodOid; } } @@ -23,8 +22,7 @@ public override int GetHashCode() { - return this.CostRatePeriodOid.HasValue ? this.GetType().Name.GetHashCode() ^ this.CostRatePeriodOid.GetHashCode() : base.GetHashCode(); + return CostRatePeriodOid.HasValue ? GetType().Name.GetHashCode() ^ CostRatePeriodOid.GetHashCode() : base.GetHashCode(); } - } } \ No newline at end of file diff --git a/Shared/DataContracts/Compact/ClientPartials/CompactOrganisationDC.cs b/Shared/DataContracts/Compact/ClientPartials/CompactOrganisationDC.cs index fb1b41b7b..915357b08 100644 --- a/Shared/DataContracts/Compact/ClientPartials/CompactOrganisationDC.cs +++ b/Shared/DataContracts/Compact/ClientPartials/CompactOrganisationDC.cs @@ -155,9 +155,9 @@ namespace BS.Shared.DataContracts.Compact public override bool Equals(object obj) { - if (obj is CompactOrganisationDC) + if (obj is CompactOrganisationDC compactOrganisation) { - return this.OrganisationOid == ((CompactOrganisationDC)obj).OrganisationOid; + return OrganisationOid == compactOrganisation.OrganisationOid; } return false; diff --git a/Shared/DataContracts/ConfirmationReceiptSignatureDC.cs b/Shared/DataContracts/ConfirmationReceiptSignatureDC.cs index c1d41e076..9928006ff 100644 --- a/Shared/DataContracts/ConfirmationReceiptSignatureDC.cs +++ b/Shared/DataContracts/ConfirmationReceiptSignatureDC.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Runtime.Serialization; +using BS.Shared.DataContracts.Compact; namespace BS.Shared.DataContracts { @@ -16,9 +17,18 @@ namespace BS.Shared.DataContracts public string SignatureImage { get; set; } [DataMember] - public long? EmployeeOid { get; set; } - + public CompactEmployeeDC Employee { get; set; } + [DataMember] public List ServiceRecords { get; set; } + + [DataMember] + public SignatureType SignatureType { get; set; } + + [DataMember] + public long? CustomerOid { get; set; } + + [DataMember] + public string TimeSpanString { get; set; } } } diff --git a/Shared/DataContracts/ContactDC.cs b/Shared/DataContracts/ContactDC.cs index ae47b4d08..dedcbb337 100644 --- a/Shared/DataContracts/ContactDC.cs +++ b/Shared/DataContracts/ContactDC.cs @@ -3,7 +3,7 @@ namespace BS.Shared.DataContracts { [DataContract] - public class ContactDC : IDataContract + public partial class ContactDC : IDataContract { [DataMember] public long? ContactOID { get; set; } diff --git a/Shared/DataContracts/ServiceRecordDC.cs b/Shared/DataContracts/ServiceRecordDC.cs index b25b647dd..81beadaa2 100644 --- a/Shared/DataContracts/ServiceRecordDC.cs +++ b/Shared/DataContracts/ServiceRecordDC.cs @@ -7,7 +7,7 @@ using BS.Shared.DataContracts.Compact; namespace BS.Shared.DataContracts { [DataContract] - public class ServiceRecordDC : IDataContract + public partial class ServiceRecordDC : IDataContract { [DataMember] public CompactOrganisationDC CostBearer { get; set; } diff --git a/Shared/Shared.csproj b/Shared/Shared.csproj index 4063cb23f..81393daf3 100644 --- a/Shared/Shared.csproj +++ b/Shared/Shared.csproj @@ -153,6 +153,7 @@ +