From 8b74dbabf55fca271167b8adbf4b92a6e7bb432e Mon Sep 17 00:00:00 2001 From: Gary Sharp Date: Thu, 19 Jun 2014 13:56:11 +1000 Subject: [PATCH] Bug Fix #49: Update group when attachment removed --- .../DocumentTemplateDevicesManagedGroup.cs | 95 ++++++++++++++----- .../DocumentTemplateManagedGroups.cs | 62 ++++++++---- .../DocumentTemplateUsersManagedGroup.cs | 95 ++++++++++++++----- .../Extensions/AttachmentActionExtensions.cs | 19 ++++ 4 files changed, 206 insertions(+), 65 deletions(-) diff --git a/Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateDevicesManagedGroup.cs b/Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateDevicesManagedGroup.cs index 0fba884e..0b16ed4d 100644 --- a/Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateDevicesManagedGroup.cs +++ b/Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateDevicesManagedGroup.cs @@ -18,7 +18,8 @@ namespace Disco.BI.DocumentTemplateBI.ManagedGroups private const string CategoryDescriptionFormat = "Related Devices Linked Group"; private const string GroupDescriptionFormat = "{0} [Document Template Devices]"; - private IDisposable repositorySubscription; + private IDisposable repositoryAddSubscription; + private IDisposable repositoryRemoveSubscription; private IDisposable deviceRenameRepositorySubscription; private IDisposable jobCloseRepositorySubscription; private IDisposable deviceAssignmentRepositorySubscription; @@ -46,24 +47,33 @@ namespace Disco.BI.DocumentTemplateBI.ManagedGroups { case DocumentTemplate.DocumentTemplateScopes.Device: // Observe Device Attachments - repositorySubscription = DocumentTemplateManagedGroups.DeviceScopeRepositoryEvents.Value + repositoryAddSubscription = DocumentTemplateManagedGroups.DeviceAttachmentAddRepositoryEvents.Value .Where(e => ((DeviceAttachment)e.Entity).DocumentTemplateId == DocumentTemplateId) - .Subscribe(ProcessDeviceRepositoryEvent); + .Subscribe(ProcessDeviceAttachmentAddEvent); + repositoryRemoveSubscription = DocumentTemplateManagedGroups.DeviceAttachmentRemoveEvents.Value + .Where(e => e.Item3 == DocumentTemplateId) + .Subscribe(ProcessDeviceAttachmentRemoveEvent); break; case DocumentTemplate.DocumentTemplateScopes.Job: // Observe Job Attachments - repositorySubscription = DocumentTemplateManagedGroups.UserScopeRepositoryEvents.Value + repositoryAddSubscription = DocumentTemplateManagedGroups.JobAttachmentAddRepositoryEvents.Value .Where(e => ((JobAttachment)e.Entity).DocumentTemplateId == DocumentTemplateId) - .Subscribe(ProcessJobRepositoryEvent); + .Subscribe(ProcessJobAttachmentAddEvent); + repositoryRemoveSubscription = DocumentTemplateManagedGroups.JobAttachmentRemoveEvents.Value + .Where(e => e.Item3 == DocumentTemplateId) + .Subscribe(ProcessJobAttachmentRemoveEvent); // Observe Job Close/Reopen jobCloseRepositorySubscription = DocumentTemplateManagedGroups.JobCloseRepositoryEvents.Value .Subscribe(ProcessJobCloseRepositoryEvent); break; case DocumentTemplate.DocumentTemplateScopes.User: // Observe User Attachments - repositorySubscription = DocumentTemplateManagedGroups.UserScopeRepositoryEvents.Value + repositoryAddSubscription = DocumentTemplateManagedGroups.UserAttachmentAddRepositoryEvents.Value .Where(e => ((UserAttachment)e.Entity).DocumentTemplateId == DocumentTemplateId) - .Subscribe(ProcessUserRepositoryEvent); + .Subscribe(ProcessUserAttachmentAddEvent); + repositoryRemoveSubscription = DocumentTemplateManagedGroups.UserAttachmentRemoveEvents.Value + .Where(e => e.Item3 == DocumentTemplateId) + .Subscribe(ProcessUserAttachmentRemoveEvent); // Observe Device Assignments deviceAssignmentRepositorySubscription = DocumentTemplateManagedGroups.DeviceAssignmentRepositoryEvents.Value .Subscribe(ProcessDeviceAssignmentRepositoryEvent); @@ -205,15 +215,26 @@ namespace Disco.BI.DocumentTemplateBI.ManagedGroups } } - private void ProcessDeviceRepositoryEvent(RepositoryMonitorEvent e) + private void ProcessDeviceAttachmentAddEvent(RepositoryMonitorEvent e) { var attachment = (DeviceAttachment)e.Entity; string deviceAccountId; if (DeviceContainsAttachment(e.Database, attachment.DeviceSerialNumber, out deviceAccountId)) AddMember(attachment.DeviceSerialNumber, (database) => new string[] { deviceAccountId }); - else if (deviceAccountId != null) - RemoveMember(attachment.DeviceSerialNumber, (database) => new string[] { deviceAccountId }); + } + private void ProcessDeviceAttachmentRemoveEvent(Tuple e) + { + var deviceSerialNumber = e.Item3; + + RemoveMember(deviceSerialNumber, (database) => + { + string deviceAccountId; + if (!DeviceContainsAttachment(database, deviceSerialNumber, out deviceAccountId) && deviceAccountId != null) + return new string[] { deviceAccountId }; + else + return null; + }); } #endregion @@ -251,7 +272,7 @@ namespace Disco.BI.DocumentTemplateBI.ManagedGroups } } - private void ProcessJobRepositoryEvent(RepositoryMonitorEvent e) + private void ProcessJobAttachmentAddEvent(RepositoryMonitorEvent e) { var attachment = (JobAttachment)e.Entity; @@ -259,8 +280,24 @@ namespace Disco.BI.DocumentTemplateBI.ManagedGroups string deviceSerialNumber; if (JobsContainAttachment(e.Database, attachment.JobId, out deviceAccountId, out deviceSerialNumber)) AddMember(deviceSerialNumber, (database) => new string[] { deviceAccountId }); - else if (deviceSerialNumber != null && deviceAccountId != null) - RemoveMember(deviceSerialNumber, (database) => new string[] { deviceAccountId }); + } + private void ProcessJobAttachmentRemoveEvent(Tuple e) + { + var jobId = e.Item4; + string deviceSerialNumber = e.Item1.Jobs.Where(j => j.Id == jobId && j.DeviceSerialNumber != null).Select(j => j.DeviceSerialNumber).FirstOrDefault(); + + if (deviceSerialNumber != null) + { + RemoveMember(deviceSerialNumber, (database) => + { + string deviceAccountId; + if (!JobsContainAttachment(database, jobId, out deviceAccountId, out deviceSerialNumber) && + deviceSerialNumber != null && deviceAccountId != null) + return new string[] { deviceAccountId }; + else + return null; + }); + } } #endregion @@ -291,21 +328,26 @@ namespace Disco.BI.DocumentTemplateBI.ManagedGroups } } - private void ProcessUserRepositoryEvent(RepositoryMonitorEvent e) + private void ProcessUserAttachmentAddEvent(RepositoryMonitorEvent e) { var attachment = (UserAttachment)e.Entity; List> devices; - if (DeviceUserContainAttachment(e.Database, attachment.UserId, out devices)) + if (DeviceUserContainAttachment(e.Database, attachment.UserId, out devices) && devices != null) + devices.ForEach(d => AddMember(d.Item2, (database) => new string[] { d.Item1 })); + } + private void ProcessUserAttachmentRemoveEvent(Tuple e) + { + var userId = e.Item4; + + RemoveMember(userId, (database) => { - if (devices != null) - devices.ForEach(d => AddMember(d.Item2, (database) => new string[] { d.Item1 })); - } - else - { - if (devices != null) - devices.ForEach(d => RemoveMember(d.Item2, (database) => new string[] { d.Item1 })); - } + List> devices; + if (!DeviceUserContainAttachment(database, userId, out devices) && devices != null) + return devices.Select(d => d.Item1); + else + return null; + }); } #endregion @@ -425,8 +467,11 @@ namespace Disco.BI.DocumentTemplateBI.ManagedGroups public override void Dispose() { - if (repositorySubscription != null) - repositorySubscription.Dispose(); + if (repositoryAddSubscription != null) + repositoryAddSubscription.Dispose(); + + if (repositoryRemoveSubscription != null) + repositoryRemoveSubscription.Dispose(); if (deviceRenameRepositorySubscription != null) deviceRenameRepositorySubscription.Dispose(); diff --git a/Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateManagedGroups.cs b/Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateManagedGroups.cs index 4538a19f..69629c1d 100644 --- a/Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateManagedGroups.cs +++ b/Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateManagedGroups.cs @@ -4,14 +4,19 @@ using Disco.Models.Repository; using System; using System.Linq; using System.Reactive.Linq; +using System.Reactive.Subjects; namespace Disco.BI.DocumentTemplateBI.ManagedGroups { public static class DocumentTemplateManagedGroups { - internal static Lazy> DeviceScopeRepositoryEvents; - internal static Lazy> JobScopeRepositoryEvents; - internal static Lazy> UserScopeRepositoryEvents; + internal static Lazy> DeviceAttachmentAddRepositoryEvents; + internal static Lazy> JobAttachmentAddRepositoryEvents; + internal static Lazy> UserAttachmentAddRepositoryEvents; + + internal static Lazy>> DeviceAttachmentRemoveEvents; + internal static Lazy>> JobAttachmentRemoveEvents; + internal static Lazy>> UserAttachmentRemoveEvents; internal static Lazy> DeviceRenameRepositoryEvents; internal static Lazy> JobCloseRepositoryEvents; @@ -19,32 +24,35 @@ namespace Disco.BI.DocumentTemplateBI.ManagedGroups static DocumentTemplateManagedGroups() { - DeviceScopeRepositoryEvents = + DeviceAttachmentAddRepositoryEvents = new Lazy>(() => RepositoryMonitor.StreamAfterCommit.Where(e => e.EntityType == typeof(DeviceAttachment) && - ((DeviceAttachment)e.Entity).DocumentTemplateId != null && ( - (e.EventType == RepositoryMonitorEventType.Added) || - (e.EventType == RepositoryMonitorEventType.Deleted) - ) + ((DeviceAttachment)e.Entity).DocumentTemplateId != null && + e.EventType == RepositoryMonitorEventType.Added )); - JobScopeRepositoryEvents = + JobAttachmentAddRepositoryEvents = new Lazy>(() => RepositoryMonitor.StreamAfterCommit.Where(e => - e.EntityType == typeof(JobAttachment) && ( - (e.EventType == RepositoryMonitorEventType.Added) || - (e.EventType == RepositoryMonitorEventType.Deleted) - ) + e.EntityType == typeof(JobAttachment) && + ((JobAttachment)e.Entity).DocumentTemplateId != null && + e.EventType == RepositoryMonitorEventType.Added )); - UserScopeRepositoryEvents = + UserAttachmentAddRepositoryEvents = new Lazy>(() => RepositoryMonitor.StreamAfterCommit.Where(e => - e.EntityType == typeof(UserAttachment) && ( - (e.EventType == RepositoryMonitorEventType.Added) || - (e.EventType == RepositoryMonitorEventType.Deleted) - ) + e.EntityType == typeof(UserAttachment) && + ((UserAttachment)e.Entity).DocumentTemplateId != null && + e.EventType == RepositoryMonitorEventType.Added )); + DeviceAttachmentRemoveEvents = + new Lazy>>(() => new Subject>()); + JobAttachmentRemoveEvents = + new Lazy>>(() => new Subject>()); + UserAttachmentRemoveEvents = + new Lazy>>(() => new Subject>()); + DeviceRenameRepositoryEvents = new Lazy>(() => RepositoryMonitor.StreamBeforeCommit.Where(e => @@ -80,5 +88,23 @@ namespace Disco.BI.DocumentTemplateBI.ManagedGroups DocumentTemplateUsersManagedGroup.Initialize(dp); }); } + + public static void TriggerDeviceAttachmentDeleted(DiscoDataContext Database, int AttachmentId, string DocumentTemplateId, string DeviceSerialNumber) + { + if (DocumentTemplateId != null) + DeviceAttachmentRemoveEvents.Value.OnNext(Tuple.Create(Database, AttachmentId, DocumentTemplateId, DeviceSerialNumber)); + } + + public static void TriggerJobAttachmentDeleted(DiscoDataContext Database, int AttachmentId, string DocumentTemplateId, int JobId) + { + if (DocumentTemplateId != null) + JobAttachmentRemoveEvents.Value.OnNext(Tuple.Create(Database, AttachmentId, DocumentTemplateId, JobId)); + } + + public static void TriggerUserAttachmentDeleted(DiscoDataContext Database, int AttachmentId, string DocumentTemplateId, string UserId) + { + if (DocumentTemplateId != null) + UserAttachmentRemoveEvents.Value.OnNext(Tuple.Create(Database, AttachmentId, DocumentTemplateId, UserId)); + } } } diff --git a/Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateUsersManagedGroup.cs b/Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateUsersManagedGroup.cs index c9bd2506..e796e4fa 100644 --- a/Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateUsersManagedGroup.cs +++ b/Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateUsersManagedGroup.cs @@ -18,7 +18,8 @@ namespace Disco.BI.DocumentTemplateBI.ManagedGroups private const string CategoryDescriptionFormat = "Related Users Linked Group"; private const string GroupDescriptionFormat = "{0} [Document Template Users]"; - private IDisposable repositorySubscription; + private IDisposable repositoryAddSubscription; + private IDisposable repositoryRemoveSubscription; private IDisposable jobCloseRepositorySubscription; private IDisposable deviceAssignmentRepositorySubscription; private string DocumentTemplateId; @@ -45,27 +46,36 @@ namespace Disco.BI.DocumentTemplateBI.ManagedGroups { case DocumentTemplate.DocumentTemplateScopes.Device: // Observe Device Attachments - repositorySubscription = DocumentTemplateManagedGroups.DeviceScopeRepositoryEvents.Value + repositoryAddSubscription = DocumentTemplateManagedGroups.DeviceAttachmentAddRepositoryEvents.Value .Where(e => ((DeviceAttachment)e.Entity).DocumentTemplateId == DocumentTemplateId) - .Subscribe(ProcessDeviceRepositoryEvent); + .Subscribe(ProcessDeviceAttachmentAddEvent); + repositoryRemoveSubscription = DocumentTemplateManagedGroups.DeviceAttachmentRemoveEvents.Value + .Where(e => e.Item3 == DocumentTemplateId) + .Subscribe(ProcessDeviceAttachmentRemoveEvent); // Observe Device Assignments deviceAssignmentRepositorySubscription = DocumentTemplateManagedGroups.DeviceAssignmentRepositoryEvents.Value .Subscribe(ProcessDeviceAssignmentRepositoryEvent); break; case DocumentTemplate.DocumentTemplateScopes.Job: // Observe Job Attachments - repositorySubscription = DocumentTemplateManagedGroups.UserScopeRepositoryEvents.Value + repositoryAddSubscription = DocumentTemplateManagedGroups.UserAttachmentAddRepositoryEvents.Value .Where(e => ((JobAttachment)e.Entity).DocumentTemplateId == DocumentTemplateId) - .Subscribe(ProcessJobRepositoryEvent); + .Subscribe(ProcessJobAttachmentAddEvent); + repositoryRemoveSubscription = DocumentTemplateManagedGroups.JobAttachmentRemoveEvents.Value + .Where(e => e.Item3 == DocumentTemplateId) + .Subscribe(ProcessJobAttachmentRemoveEvent); // Observe Job Close/Reopen jobCloseRepositorySubscription = DocumentTemplateManagedGroups.JobCloseRepositoryEvents.Value .Subscribe(ProcessJobCloseRepositoryEvent); break; case DocumentTemplate.DocumentTemplateScopes.User: // Observe User Attachments - repositorySubscription = DocumentTemplateManagedGroups.UserScopeRepositoryEvents.Value + repositoryAddSubscription = DocumentTemplateManagedGroups.UserAttachmentAddRepositoryEvents.Value .Where(e => ((UserAttachment)e.Entity).DocumentTemplateId == DocumentTemplateId) - .Subscribe(ProcessUserRepositoryEvent); + .Subscribe(ProcessUserAttachmentAddEvent); + repositoryRemoveSubscription = DocumentTemplateManagedGroups.UserAttachmentRemoveEvents.Value + .Where(e => e.Item3 == DocumentTemplateId) + .Subscribe(ProcessUserAttachmentRemoveEvent); break; } } @@ -82,7 +92,7 @@ namespace Disco.BI.DocumentTemplateBI.ManagedGroups case DocumentTemplate.DocumentTemplateScopes.Job: return string.Format(DescriptionFormat, DocumentTemplateScope, DocumentTemplateDescription); case DocumentTemplate.DocumentTemplateScopes.User: - return string.Format(UserDescriptionFormat, DocumentTemplateDescription); + return string.Format(UserDescriptionFormat, DocumentTemplateDescription); default: throw new ArgumentException("Unknown Document Template Scope", "Scope"); } @@ -183,15 +193,29 @@ namespace Disco.BI.DocumentTemplateBI.ManagedGroups } } - private void ProcessDeviceRepositoryEvent(RepositoryMonitorEvent e) + private void ProcessDeviceAttachmentAddEvent(RepositoryMonitorEvent e) { var attachment = (DeviceAttachment)e.Entity; string userId; - if (DeviceContainsAttachment(e.Database, attachment.DeviceSerialNumber, out userId)) + if (DeviceContainsAttachment(e.Database, attachment.DeviceSerialNumber, out userId) && userId != null) AddMember(userId, (database) => new string[] { userId }); - else if (userId != null) - RemoveMember(userId, (database) => new string[] { userId }); + } + private void ProcessDeviceAttachmentRemoveEvent(Tuple e) + { + var deviceSerialNumber = e.Item4; + string userId = e.Item1.Devices.Where(d => d.SerialNumber == deviceSerialNumber && d.AssignedUserId != null).Select(j => j.AssignedUserId).FirstOrDefault(); + + if (userId != null) + { + RemoveMember(userId, (database) => + { + if (DeviceContainsAttachment(database, deviceSerialNumber, out userId) && userId != null) + return new string[] { userId }; + else + return null; + }); + } } #endregion @@ -217,15 +241,29 @@ namespace Disco.BI.DocumentTemplateBI.ManagedGroups } } - private void ProcessJobRepositoryEvent(RepositoryMonitorEvent e) + private void ProcessJobAttachmentAddEvent(RepositoryMonitorEvent e) { var attachment = (JobAttachment)e.Entity; string userId; - if (JobsContainAttachment(e.Database, attachment.JobId, out userId)) + if (JobsContainAttachment(e.Database, attachment.JobId, out userId) && userId != null) AddMember(userId, (database) => new string[] { userId }); - else if (userId != null) - RemoveMember(userId, (database) => new string[] { userId }); + } + private void ProcessJobAttachmentRemoveEvent(Tuple e) + { + var jobId = e.Item4; + string userId = e.Item1.Jobs.Where(j => j.Id == jobId && j.UserId != null).Select(j => j.UserId).FirstOrDefault(); + + if (userId != null) + { + RemoveMember(userId, (database) => + { + if (JobsContainAttachment(database, jobId, out userId) && userId != null) + return new string[] { userId }; + else + return null; + }); + } } #endregion @@ -239,15 +277,25 @@ namespace Disco.BI.DocumentTemplateBI.ManagedGroups return result; } - private void ProcessUserRepositoryEvent(RepositoryMonitorEvent e) + private void ProcessUserAttachmentAddEvent(RepositoryMonitorEvent e) { var attachment = (UserAttachment)e.Entity; var userId = attachment.UserId; - if (UserContainAttachment(e.Database, userId)) + if (UserContainAttachment(e.Database, userId) && userId != null) AddMember(userId, (database) => new string[] { userId }); - else - RemoveMember(userId, (database) => new string[] { userId }); + } + private void ProcessUserAttachmentRemoveEvent(Tuple e) + { + var userId = e.Item4; + + RemoveMember(userId, (database) => + { + if (!UserContainAttachment(database, userId)) + return new string[] { userId }; + else + return null; + }); } #endregion @@ -301,8 +349,11 @@ namespace Disco.BI.DocumentTemplateBI.ManagedGroups public override void Dispose() { - if (repositorySubscription != null) - repositorySubscription.Dispose(); + if (repositoryAddSubscription != null) + repositoryAddSubscription.Dispose(); + + if (repositoryRemoveSubscription != null) + repositoryRemoveSubscription.Dispose(); if (jobCloseRepositorySubscription != null) jobCloseRepositorySubscription.Dispose(); diff --git a/Disco.BI/BI/Extensions/AttachmentActionExtensions.cs b/Disco.BI/BI/Extensions/AttachmentActionExtensions.cs index 2b129a7a..b582301a 100644 --- a/Disco.BI/BI/Extensions/AttachmentActionExtensions.cs +++ b/Disco.BI/BI/Extensions/AttachmentActionExtensions.cs @@ -6,6 +6,7 @@ using Disco.Models.Repository; using Disco.Data.Repository; using Disco.Services.Users; using Disco.Services.Authorization; +using Disco.BI.DocumentTemplateBI.ManagedGroups; namespace Disco.BI.Extensions { @@ -29,8 +30,14 @@ namespace Disco.BI.Extensions if (!da.CanDelete()) throw new InvalidOperationException("Deletion of Attachment is Denied"); + var attachmentId = da.Id; + var documentTemplateId = da.DocumentTemplateId; + var deviceSerialNumber = da.DeviceSerialNumber; + da.RepositoryDelete(Database); Database.DeviceAttachments.Remove(da); + + DocumentTemplateManagedGroups.TriggerDeviceAttachmentDeleted(Database, attachmentId, documentTemplateId, deviceSerialNumber); } public static bool CanDelete(this JobAttachment ja) { @@ -48,8 +55,14 @@ namespace Disco.BI.Extensions if (!ja.CanDelete()) throw new InvalidOperationException("Deletion of Attachment is Denied"); + var attachmentId = ja.Id; + var documentTemplateId = ja.DocumentTemplateId; + var jobId = ja.JobId; + ja.RepositoryDelete(Database); Database.JobAttachments.Remove(ja); + + DocumentTemplateManagedGroups.TriggerJobAttachmentDeleted(Database, attachmentId, documentTemplateId, jobId); } public static bool CanDelete(this UserAttachment ua) { @@ -67,8 +80,14 @@ namespace Disco.BI.Extensions if (!ua.CanDelete()) throw new InvalidOperationException("Deletion of Attachment is Denied"); + var attachmentId = ua.Id; + var documentTemplateId = ua.DocumentTemplateId; + var userId = ua.UserId; + ua.RepositoryDelete(Database); Database.UserAttachments.Remove(ua); + + DocumentTemplateManagedGroups.TriggerUserAttachmentDeleted(Database, attachmentId, documentTemplateId, userId); } #endregion