Files
BeWoPlaner/BeWoPlanerMobil/Controllers/ExternalSignatureController.cs

511 lines
20 KiB
C#

using System;
using System.Configuration;
using System.IO;
using System.Linq;
using System.ServiceModel;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web.Mvc;
using BeWo.Data.Entities;
using BeWo.Data.Utils;
using BeWo.Service.DCEntityMapper;
using BeWo.Service.Security;
using BeWoPlanerMobil.Models;
using BeWoPlanerMobil.Service;
using BeWoPlanerMobil.Util;
using BS.Shared;
using NHibernate;
using NHibernate.Criterion;
namespace BeWoPlanerMobil.Controllers
{
public class ExternalSignatureController : Controller
{
private static readonly object Lock = string.Empty;
protected static readonly log4net.ILog Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private ExternalSignatureModel _Model;
public ExternalSignatureModel Model
{
get
{
if((ExternalSignatureModel) Session["ExternalSignatureModel"] is null)
{
_Model = new ExternalSignatureModel();
Session["ExternalSignatureModel"] = _Model;
}
else
{
_Model = (ExternalSignatureModel) Session["ExternalSignatureModel"];
}
return _Model ?? new ExternalSignatureModel();
}
}
private bool IsTokenExpired()
{
if(Model?.Token is null)
{
return true;
}
try
{
var info = SecurityUtils.SliceOneTimeLinkToken(Model.Token);
if(info.ContainsKey("expirationDate") && DateTime.TryParse(info["expirationDate"]?.ToString(), out var expirationDate))
{
return expirationDate < DateTime.Now;
}
return true;
}
catch(Exception exception)
{
Log.Error(exception.Message, exception);
return true;
}
}
private bool CheckCredentials()
{
if(Model?.Token is null)
{
return false;
}
var info = SecurityUtils.SliceOneTimeLinkToken(Model.Token);
var username = info["user"].ToString();
var password = info["password"].ToString();
var session = CreateSessionFromTokenInfo();
if(session is null)
{
return false;
}
try
{
var user = session.CreateCriteria<ApplicationUser>()
.Add(Restrictions.Eq(nameof(ApplicationUser.LoginName), username))
.Add(Restrictions.Eq(nameof(BeWoEntityBase.IsActive), BS.Shared.ActivationTypeId.Active))
.UniqueResult<ApplicationUser>();
if(!(user is null) && user.CheckRC2Password(password))
{
return user.CheckRC2Password(password);
}
Model.ErrorMessage = "Es ist ein Fehler aufgetreten.<br />Bitte wenden Sie sich an Ihren Administrator";
#if DEBUG
//Model.ErrorMessage = $"Es wurde kein Benutzer mit dem Loginnamen {username} gefunden oder das Passwort stimmt nicht überein!";
#endif
return false;
}
catch(Exception exception)
{
throw exception;
}
finally
{
session.Close();
}
}
private ISession CreateSessionFromTokenInfo()
{
try
{
Monitor.Enter(Lock);
var test = System.Web.HttpContext.Current.Server.MapPath("");
var dotDotCount = Regex.Matches(test, "ExternalSignature").Count;
var mapPathParameter = "";
for(var i = 0; i < dotDotCount; i++)
{
mapPathParameter += "..\\";
}
var serverPath = System.Web.HttpContext.Current.Server.MapPath(mapPathParameter);
serverPath = Path.Combine(serverPath, ConfigurationManager.AppSettings.Get("MultitenancyPath"));
serverPath = Path.Combine(serverPath, $"{Model.Tenant}.config");
if(!System.IO.File.Exists(serverPath))
{
Model.ErrorMessage = "Es ist ein Fehler aufgetreten.<br />Bitte wenden Sie sich an Ihren Administrator";
#if DEBUG
//Model.ErrorMessage = "Die .config-Datei wurde nicht gefunden!";
#endif
return null;
}
var config = new NHibernate.Cfg.Configuration().Configure(serverPath).SetInterceptor(new MobileUpdInsInterceptor()).BuildSessionFactory();
return config.OpenSession();
}
catch(Exception exception)
{
throw new FaultException(exception.StackTrace + (exception.InnerException?.Message ?? string.Empty));
}
finally
{
Monitor.Exit(Lock);
}
}
private ServiceRecord LoadServiceRecord()
{
try
{
if(false == CheckCredentials() || IsTokenExpired())
{
return null;
}
var session = CreateSessionFromTokenInfo();
try
{
if(Model.ServiceRecordOid is null)
{
return null;
}
return session.CreateCriteria<ServiceRecord>()
.Add(Restrictions.Eq(nameof(BeWoEntityBase.Oid), Model.ServiceRecordOid))
.Add(Restrictions.Eq(nameof(BeWoEntityBase.IsActive), ActivationTypeId.Active))
.UniqueResult<ServiceRecord>();
}
catch(Exception exception)
{
throw exception;
}
finally
{
session.Close();
}
}
catch(Exception exception)
{
Log.Error(exception.Message, exception);
return null;
}
}
public ActionResult ExternalSignature(string token)
{
if(token is null)
{
Model.ErrorMessage = "Es ist ein Fehler aufgetreten.<br />Bitte wenden Sie sich an Ihren Administrator";
#if DEBUG
Model.ErrorMessage = "Token ist null!";
#endif
return View(Model);
}
try
{
Model.Token = token;
var info = SecurityUtils.SliceOneTimeLinkToken(token);
if(IsTokenExpired())
{
Model.ErrorMessage = "Der Link ist abgelaufen!";
return View(Model);
}
Model.Tenant = info["tenant"].ToString();
var username = info["user"].ToString();
var serviceRecordOid = long.Parse(info["serviceRecordOid"].ToString());
var session = CreateSessionFromTokenInfo();
if(session is null)
{
return View(Model);
}
if(false == CheckCredentials())
{
Model.ErrorMessage = "Es ist ein Fehler aufgetreten.<br />Bitte wenden Sie sich an Ihren Administrator.";
#if DEBUG
//Model.ErrorMessage = $"Es wurde kein Benutzer mit dem Loginnamen {username} gefunden oder das Passwort stimmt nicht überein!";
#endif
return View(Model);
}
try
{
var serviceRecord = session.CreateCriteria<ServiceRecord>()
.Add(Restrictions.Eq(nameof(BeWoEntityBase.Oid), serviceRecordOid))
.Add(Restrictions.Eq(nameof(BeWoEntityBase.IsActive), BS.Shared.ActivationTypeId.Active))
.UniqueResult<ServiceRecord>();
if(serviceRecord is null)
{
Model.ErrorMessage = "Es ist ein Fehler aufgetreten.<br />Bitte wenden Sie sich an Ihren Administrator.";
#if DEBUG
//Model.TestInfo = $"Es wurde kein ServiceRecord mit der Oid {serviceRecordOid} gefunden!";
#endif
return View(Model);
}
if(serviceRecord.SignatureOid.HasValue)
{
Model.HasSignatureAlready = true;
return View(Model);
}
var auswahlBezeichnung = serviceRecord.CostBearer2SupportConcept.AuswahlBezeichnung;
var cb2ScStart = serviceRecord.CostBearer2SupportConcept.StartDate?.ToShortDateString().Remove(6, 2) ?? string.Empty;
var cb2ScEnd = serviceRecord.CostBearer2SupportConcept.EndDate?.ToShortDateString().Remove(6, 2) ?? string.Empty;
var costBearerName = serviceRecord.CostBearer2SupportConcept.CostBearer.Organisation.Name;
var approvalInfo = GetIsNotApproved(serviceRecord.CostBearer2SupportConcept);
var customerDC = MapperFactory.CompactCustomerDC_Customer.MapToNewDC(serviceRecord.Customer);
Model.SupportConceptInfo = $"{customerDC.SimpleDescription} {customerDC.DateOfBirthString ?? string.Empty} | {auswahlBezeichnung} {cb2ScStart}-{cb2ScEnd} {costBearerName}{approvalInfo}";
Model.ServiceDescriptionInfo = serviceRecord.ServiceDescription.Name;
Model.CategoryInfo = serviceRecord.ServiceDescription.ServiceCategory.Name;
Model.EmployeeInfo = serviceRecord.Employee.Person.LastNameFirstName;
Model.ServiceRecordDateTime = MainModel.GetServiceRecordTimeString(MapperFactory.ServiceRecordDC_ServiceRecord.MapToNewDC(serviceRecord));
Model.ServiceRecordOid = serviceRecord.Oid;
Model.CustomerName = customerDC.Name;
}
catch(Exception exception)
{
throw exception;
}
finally
{
session.Close();
}
}
catch(Exception exception)
{
Log.Error(exception.Message, exception);
Model.ErrorMessage = exception.Message + "<br/><br/>" + exception.StackTrace;
}
return View(Model);
}
public string SaveSignature(string base64Image, DateTime creationDate)
{
try
{
long? oid;
using(var signatureBitmap = SignatureUtils.Base64StringToBitmap(base64Image.Split(',')[1]))
{
var isValid = SignatureUtils.ValidateSignature(signatureBitmap);
if(!isValid)
{
return "Das Unterschriftenfeld darf nicht leer sein.";
}
var signature = new Signature
{
DataBild = base64Image,
IsActive = ActivationTypeId.Active,
ServiceRecordOid = Model.ServiceRecordOid,
Zeitstempel = creationDate
};
Insert(signature);
oid = signature.Oid;
var serviceRecord = LoadServiceRecord();
serviceRecord.SignatureOid = signature.Oid;
var session = CreateSessionFromTokenInfo();
if(session is null)
{
throw new InvalidOperationException("Database session is null!");
}
var transaction = session.BeginTransaction();
try
{
BeWo.Service.Core.ServiceLogic.ConcurrencyCheck(serviceRecord.Version, LoadServiceRecord());
session.Update(serviceRecord);
transaction.Commit();
transaction = session.BeginTransaction();
var previousRecordHistorySignatureInfo = FindMostRecentSignatureStatusInfo();
var seviceRecordHistoryEntry = new ServiceRecordHistory
{
TimeStamp = DateTime.Now,
ChangeType = StatementType.Signature,
CostBearer2SupportConcept = serviceRecord.CostBearer2SupportConcept,
CostBearer2SupportConceptOid = serviceRecord.CostBearer2SupportConceptOid,
Customer = serviceRecord.Customer,
CustomerOid = serviceRecord.CustomerOid,
Employee = serviceRecord.Employee,
EmployeeOid = serviceRecord.EmployeeOid,
End = serviceRecord.End,
Group = serviceRecord.Group,
GroupEmployeeCount = serviceRecord.GroupEmployeeCount,
GroupOid = serviceRecord.GroupOid,
GroupPersonCount = serviceRecord.GroupPersonCount,
GroupRoundedDuration = serviceRecord.GroupRoundedDuration,
IP = serviceRecord.IP,
IsActive = serviceRecord.IsActive,
Notice = serviceRecord.Notice,
ServiceRecordOid = serviceRecord.Oid,
RoundedDuration = serviceRecord.RoundedDuration,
ServiceDescription = serviceRecord.ServiceDescription,
ServiceRecordType = serviceRecord.ServiceRecordType,
ServiceRecordInsTs = serviceRecord.InsTs,
ServiceRecordVersion = serviceRecord.Version.Value,
ServiceRecordInsUser = serviceRecord.InsUser,
ServiceRecordUdpUser = serviceRecord.UdpUser,
Start = serviceRecord.Start,
SupportConcept = serviceRecord.SupportConcept,
SystemEntryID = serviceRecord.SystemEntryID,
DistanceInMeter = serviceRecord.DistanceInMeter,
IsCreatedInMobileClient = serviceRecord.IsCreatedInMobileClient,
CustomerConfirmationReceiptSignatureStateType = SignatureStateType.Valid,
EmployeeConfirmationReceiptSignatureStateType = previousRecordHistorySignatureInfo?.EmployeeConfirmationReceiptSignatureStateType ?? SignatureStateType.None,
ServiceRecordSignatureStateType = previousRecordHistorySignatureInfo?.ServiceRecordSignatureStateType ?? SignatureStateType.None,
CustomerConfirmationReceiptSignatureOid = previousRecordHistorySignatureInfo?.CustomerConfirmationReceiptSignatureOid,
EmployeeConfirmationReceiptSignatureOid = previousRecordHistorySignatureInfo?.EmployeeConfirmationReceiptSignatureOid
};
session.Save(seviceRecordHistoryEntry);
transaction.Commit();
}
catch(Exception exception)
{
transaction.Rollback();
throw exception;
}
finally
{
session.Close();
}
}
return oid.HasValue ? "1" : "0";
}
catch(Exception outerException)
{
Log.Error(outerException.Message, outerException);
return "0";
}
}
private void Insert(BeWoEntityBase entity)
{
try
{
var session = CreateSessionFromTokenInfo();
if(session is null || false == CheckCredentials())
{
throw new InvalidOperationException("Database session is null!");
}
var transaction = session.BeginTransaction();
try
{
session.Save(entity);
transaction.Commit();
}
catch(Exception exception)
{
transaction.Rollback();
throw exception;
}
finally
{
session.Close();
}
}
catch(Exception exception)
{
Log.Error(exception.Message, exception);
}
}
private SignatureStateInfoFromServiceRecordHistoryEntry FindMostRecentSignatureStatusInfo()
{
var session = CreateSessionFromTokenInfo();
var sqlQuery = session.CreateSQLQuery($"SELECT * FROM ServiceRecordHistory WHERE ServiceRecordOid = {Model.ServiceRecordOid} ORDER BY InsTs DESC LIMIT 1")
.AddScalar("CustomerConfirmationReceiptSignatureStateType", NHibernateUtil.Int32)
.AddScalar("EmployeeConfirmationReceiptSignatureStateType", NHibernateUtil.Int32)
.AddScalar("ServiceRecordSignatureStateType", NHibernateUtil.Int32)
.AddScalar("CustomerConfirmationReceiptSignatureOid", NHibernateUtil.Int64)
.AddScalar("EmployeeConfirmationReceiptSignatureOid", NHibernateUtil.Int64);
var objectsList = sqlQuery.List<object[]>().ToList();
var row = objectsList.FirstOrDefault();
if(row is null || row.Length != 5)
{
return null;
}
var customerConfirmationReceiptSignatureState = (SignatureStateType) row[0];
var employeeConfirmationReceiptSignatureState = (SignatureStateType) row[1];
var serviceRecordSignatureStateType = (SignatureStateType) row[2];
var customerConfirmationReceiptSignatureOid = (long?) row[3];
var employeeConfirmationReceiptSignatureOid = (long?) row[4];
return new SignatureStateInfoFromServiceRecordHistoryEntry(customerConfirmationReceiptSignatureState, employeeConfirmationReceiptSignatureState, serviceRecordSignatureStateType, customerConfirmationReceiptSignatureOid, employeeConfirmationReceiptSignatureOid);
}
private static string GetIsNotApproved(CostBearer2SupportConcept costBearer2SupportConcept)
{
var result = string.Empty;
var customer = costBearer2SupportConcept?.SupportConcept?.Customer;
if(customer?.TerminationDate.HasValue ?? false)
{
var terminationReason = string.Empty;
if(!string.IsNullOrEmpty(customer.TerminationReason.Value))
{
terminationReason += $", Begründung: {customer.TerminationReason}";
}
result += $" (Betreuung beendet am: {customer.TerminationDate:dd.MM.yyyy}{terminationReason})";
}
if(costBearer2SupportConcept?.ApprovedStartDate is null || costBearer2SupportConcept.ApprovedEndDate is null)
{
result += " nicht bewilligt!";
}
return result;
}
}
}