using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using BeWo.Data.Entities; using BeWo.Data.Entities.Light; using BS.Shared; using BS.Shared.Extensions; using NHibernate; using NHibernate.Criterion; using NHibernate.Proxy; using NHibernate.Linq; namespace BeWo.Data.Access { public class GenericDAO : AbstractBaseDAO { internal GenericDAO() { } public virtual void Deactivate(BeWoEntityBase pEntity) { Debug.WriteLine($"---->DEACTIVATE von {pEntity.GetType().FullName}"); this.SetActivationType(pEntity, ActivationTypeId.Deleted); } public virtual void Deactivate(IEnumerable pEntitys) where T : BeWoEntityBase, new() { if (pEntitys?.FirstOrDefault() is object obj) { Debug.WriteLine($"---->DEACTIVATE von {obj.GetType().FullName}"); } ITransaction lTransaction = this.Session.BeginTransaction(); try { foreach (BeWoEntityBase iEntity in pEntitys) { iEntity.IsActive = ActivationTypeId.Deleted; if (iEntity.SystemEntryID == null) { this.Session.SaveOrUpdate(iEntity); } else { throw new InvalidOperationException("Can't delete System Entries"); } } lTransaction.Commit(); } catch (Exception e) { lTransaction.Rollback(); throw e; } } public virtual void Delete(BeWoEntityBase pEntity) { Debug.WriteLine($"---->DELETE von {pEntity.GetType().FullName}"); if (pEntity.SystemEntryID is null) { LogSignatureDeletion(pEntity); var lTransaction = Session.BeginTransaction(); try { Session.Delete(pEntity); lTransaction.Commit(); } catch (Exception e) { lTransaction.Rollback(); throw e; } } else { throw new InvalidOperationException("Can't delete System Entries"); } } public virtual void Delete(IEnumerable pEntitys) where T : BeWoEntityBase, new() { if (pEntitys?.FirstOrDefault() is object obj) { Debug.WriteLine($"---->DELETE von {obj.GetType().FullName}"); } var entities = pEntitys.ToList(); foreach (var entity in entities) { LogSignatureDeletion(entity); } var lTransaction = Session.BeginTransaction(); try { foreach (var iEntity in entities) { if (iEntity.SystemEntryID is null || iEntity.SystemEntryID.Value == SystemEntryID.AdditionalServiceAssessmentSheet) { Session.Delete(iEntity); } else { throw new InvalidOperationException("Can't delete System Entries"); } } lTransaction.Commit(); } catch (Exception e) { lTransaction.Rollback(); throw e; } } public virtual IList GetAll() where T : BeWoEntityBase { return this.CreateCriteria().List(); } public virtual IList GetAllWithoutPermanentlyDeleted() where T : BeWoEntityBase { return this.CreateCriteria().Add(Restrictions.Or(Restrictions.IsNull(BeWoEntityBase.PropertyName_SystemEntryID), Restrictions.Not(Restrictions.Eq(BeWoEntityBase.PropertyName_SystemEntryID, SystemEntryID.DeletedPermanently)))).List(); } public virtual IList GetAllActive() where T : BeWoEntityBase { return this.GetAllWithActivationType(ActivationTypeId.Active); } public virtual IList GetAllActiveAndArchived() where T : BeWoEntityBase { return this.CreateCriteria().Add(Restrictions.Or(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active), Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Archived))).List(); } public virtual IList GetAllWithActivationType(ActivationTypeId activationType) where T : BeWoEntityBase { return this.CreateCriteria().Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, activationType)).List(); } public virtual T GetByID(long pOid) where T : BeWoEntityBase, new() { return this.Session.Get(pOid); } public virtual List GetByIDs(IEnumerable pOids) where T : BeWoEntityBase, new() { return pOids.Select(oid => this.GetByID(oid)).ToList(); } public virtual IList GetActiveByIDs(IEnumerable pOids) where T : BeWoEntityBase, new() { return CreateCriteria().Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active)).Add(Restrictions.In(BeWoEntityBase.PropertyName_Oid, pOids.ToArray())).List(); } public virtual void Insert(BeWoEntityBase pEntity) { var entityType = pEntity.GetType(); Debug.WriteLine($"++++>INSERT von {entityType.FullName}"); if (pEntity is LightEntity) throw new InvalidOperationException("Cannot insert LightEntity, only update! str:" + pEntity.ToString()); var session = Session; if (session is null) { throw new InvalidOperationException("GenericDAO.Insert(): Session is null"); } var lTransaction = session.BeginTransaction(); try { pEntity.IsActive = ActivationTypeId.Active; session.Save(pEntity); lTransaction.Commit(); if (pEntity is Signature signature) { LogSignatureInsert(signature); } } catch (Exception e) { lTransaction.Rollback(); throw e; } } public virtual void Insert(IEnumerable pEntitys) where T : BeWoEntityBase, new() { if (pEntitys?.FirstOrDefault() is object obj) { Debug.WriteLine($"++++>INSERT von {obj.GetType().FullName}"); } ITransaction lTransaction = this.Session.BeginTransaction(); try { foreach (BeWoEntityBase iEntity in pEntitys) { if (iEntity is LightEntity) throw new InvalidOperationException("Cannot insert LightEntity, only update! str:" + iEntity.ToString()); this.Session.Save(iEntity); } lTransaction.Commit(); } catch (Exception e) { lTransaction.Rollback(); throw e; } } public virtual T LoadByID(long pOid) where T : BeWoEntityBase, new() { return this.Session.Load(pOid); } public virtual List LoadByIDs(IEnumerable pOids) where T : BeWoEntityBase, new() { return pOids.Select(oid => this.LoadByID(oid)).ToList(); } public virtual T LoadSystemEntry(SystemEntryID pId) where T : BeWoEntityBase, new() { return this.CreateCriteria().Add(Restrictions.Eq(BeWoEntityBase.PropertyName_SystemEntryID, pId)).UniqueResult(); } public void Reattach(T entity) where T : BeWoEntityBase, new() { this.Session.Lock(entity, LockMode.None); } public virtual void SetActivationType(IEnumerable pEntities, ActivationTypeId activationType) { pEntities.ForEach(x => SetActivationType(x, activationType)); } public virtual void SetActivationType(BeWoEntityBase pEntity, ActivationTypeId activationType) { if (pEntity.SystemEntryID == null) { ITransaction lTransaction = this.Session.BeginTransaction(); try { pEntity.IsActive = activationType; this.Session.SaveOrUpdate(pEntity); lTransaction.Commit(); } catch (Exception e) { lTransaction.Rollback(); throw e; } } else { throw new InvalidOperationException("Can't delete System Entries"); } } public virtual void Update(BeWoEntityBase pEntity) { Debug.WriteLine($"####>UPDATE von {pEntity.GetType().FullName}"); if (pEntity is ServiceRecord serviceRecord && serviceRecord.Oid.HasValue) { var hasPreviouslyExistingSignature = DAOFactory.SearchDAO.CheckForExistingServiceRecordSignature(serviceRecord.Oid.Value); if (hasPreviouslyExistingSignature && serviceRecord.SignatureOid is null) { LogSignatureDeletion(serviceRecord); } } if (pEntity is Bargeldkasse bargeldkasse && bargeldkasse.Oid.HasValue) { var oldTransactions = DAOFactory.SearchDAO.LoadBargeldTransaktionenNonLazy(bargeldkasse.Oid.Value); var deletedTransactions = oldTransactions.Where(oldTransaction => false == bargeldkasse.Bargeldtransaktionen.Any(x => x.Oid.HasValue && x.Oid.Equals(oldTransaction.Oid))).ToList(); var deletedTransactionsWithSignature = deletedTransactions.Where(oldTransaction => oldTransaction.SignatureOid.HasValue).ToList(); foreach (var deletedTransactionWithSignature in deletedTransactionsWithSignature) { LogSignatureDeletion(deletedTransactionWithSignature); } } ITransaction lTransaction = this.Session.BeginTransaction(); try { this.Session.SaveOrUpdate(pEntity); lTransaction.Commit(); } catch (Exception e) { lTransaction.Rollback(); throw e; } } public virtual void Update(IEnumerable pEntities) where T : BeWoEntityBase, new() { if (pEntities?.FirstOrDefault() is object obj) { Debug.WriteLine($"####>UPDATE von {obj.GetType().FullName}"); } ITransaction lTransaction = this.Session.BeginTransaction(); try { if (pEntities is IEnumerable serviceRecords) { foreach (var serviceRecord in serviceRecords) { if (serviceRecord.Oid is null) { continue; } var hasPreviouslyExistingSignature = DAOFactory.SearchDAO.CheckForExistingServiceRecordSignature(serviceRecord.Oid.Value); if (hasPreviouslyExistingSignature && serviceRecord.SignatureOid is null) { LogSignatureDeletion(serviceRecord); } } } if (pEntities is IEnumerable bargeldkassen) { foreach (var bargeldkasse in bargeldkassen) { if (bargeldkasse.Oid is null) { continue; } var oldTransactions = DAOFactory.SearchDAO.LoadBargeldTransaktionenNonLazy(bargeldkasse.Oid.Value); var deletedTransactions = oldTransactions.Where(oldTransaction => bargeldkasse.Bargeldtransaktionen.Any(x => x.Oid.HasValue && x.Oid.Equals(oldTransaction.Oid))).ToList(); var deletedTransactionsWithSignature = deletedTransactions.Where(oldTransaction => oldTransaction.SignatureOid.HasValue).ToList(); foreach (var deletedTransactionWithSignature in deletedTransactionsWithSignature) { LogSignatureDeletion(deletedTransactionWithSignature); } } } foreach (BeWoEntityBase iEntity in pEntities) { this.Session.SaveOrUpdate(iEntity); } lTransaction.Commit(); } catch (Exception e) { lTransaction.Rollback(); throw e; } } public virtual T Unproxy(T obj) { if (!NHibernateUtil.IsInitialized(obj)) { NHibernateUtil.Initialize(obj); } if (obj is INHibernateProxy) { return (T)this.Session.GetSessionImplementation().PersistenceContext.Unproxy(obj); } return obj; } public virtual int GetRowCount() where T : BeWoEntityBase { return Session.QueryOver().RowCount(); } public virtual int GetRowCount(string pPropertyName, object value) where T : BeWoEntityBase { var count = CreateCriteria() .Add(Restrictions.Eq(pPropertyName, value)) .SetProjection(Projections.RowCount()) .UniqueResult(); return count; } public virtual bool Any() where T : BeWoEntityBase { return GetRowCount() > 0; } public virtual bool Any(string pPropertyName, object value) where T : BeWoEntityBase { return GetRowCount(pPropertyName, value) > 0; } public virtual bool Exists(string pPropertyName, object value) where T : BeWoEntityBase { return GetRowCount(pPropertyName, value) > 0; } public T GetByProperty(string pPropertyName, object value) where T : BeWoEntityBase { return CreateCriteria().Add(Restrictions.Eq(pPropertyName, value)).UniqueResult(); } private static void LogSignatureDeletion(BeWoEntityBase entity) { var signatureHistoryEntries = new List(); switch (entity) { case Signature signature: signatureHistoryEntries.AddIfNotNull(DAOFactory.SearchDAO.CreateSignatureHistoryEntry(signature, SignatureEventType.Delete)); break; case ConfirmationReceiptSignature confirmationReceiptSignature: signatureHistoryEntries.AddIfNotNull(DAOFactory.SearchDAO.CreateMonthlySignatureHistoryEntry(confirmationReceiptSignature, SignatureEventType.Delete)); break; case ServiceRecord serviceRecord when serviceRecord.Oid.HasValue: { var s = DAOFactory.SearchDAO.LoadJustDeletedSignature(serviceRecord.Oid.Value, true); var signatureHistoryEntry = DAOFactory.SearchDAO.CreateSignatureHistoryEntry(s, SignatureEventType.CascadingDelete); signatureHistoryEntries.AddIfNotNull(signatureHistoryEntry); break; } case Bargeldkasse bargeldkasse when bargeldkasse.Bargeldtransaktionen.Any(bargeldtransaktion => bargeldtransaktion.SignatureOid.HasValue): signatureHistoryEntries.AddRangeIfNotNull(DAOFactory.SearchDAO.CreateSignatureHistoryEntryForBargeldkasse(bargeldkasse)); break; case Bargeldtransaktion bargeldtransaktion when bargeldtransaktion.SignatureOid.HasValue: signatureHistoryEntries.AddIfNotNull(DAOFactory.SearchDAO.CreateSignatureHistoryForBargeldtransaktion(bargeldtransaktion, SignatureEventType.CascadingDelete)); break; } if (signatureHistoryEntries.Any()) { DAOFactory.GenericDAO.Insert(signatureHistoryEntries.Where(she => she is object)); } } private static void LogSignatureUpdateForServiceRecord(ServiceRecord serviceRecord) { /* * Wird bei folgenden Szenarien ausgeführt: * * 1. Direkt nach dem Signature-Insert (Erst das Signature-Insert, dann das ServiceRecord-Update, um die SignatureOid in die ServiceRecord-Tabelle zu schreiben). * 2. Beim Löschen der Signature */ var hasPreviouslyExistingSignature = DAOFactory.SearchDAO.CheckForExistingServiceRecordSignature(serviceRecord.Oid.Value); // Prüfen, ob es sich um ein Update, ausgelöst durch das Insert der Unterschrift, handelt. if (false == hasPreviouslyExistingSignature) { return; } var signatureHistory = DAOFactory.SearchDAO.CreateSignatureHistoryForServiceRecordUpdate(serviceRecord, SignatureEventType.CascadingDelete); DAOFactory.GenericDAO.Insert(signatureHistory); } private static void LogSignatureInsert(Signature signature) { var signatureHistory = DAOFactory.SearchDAO.CreateSignatureHistoryEntry(signature, SignatureEventType.Insert); DAOFactory.GenericDAO.Insert(signatureHistory); } } }