Feature: Job Queues

Also UI style, theme and element changes
This commit is contained in:
Gary Sharp
2014-02-03 14:50:08 +11:00
parent bdb3e1e6b4
commit 3f63281dc4
212 changed files with 17334 additions and 5441 deletions
@@ -1,5 +1,5 @@
using Disco.Data.Repository;
using Disco.Models.Authorization;
using Disco.Models.Services.Authorization;
using Disco.Models.Repository;
using Disco.Services.Users;
using System;
+49 -25
View File
@@ -338,20 +338,53 @@ namespace Disco.BI.Extensions
#endregion
#region Close
public static bool CanClose(this Job j)
public static void OnCloseNormally(this Job j, User Technician)
{
if (!j.CanCloseNormally())
throw new InvalidOperationException("Close was Denied");
j.ClosedDate = DateTime.Now;
j.ClosedTechUserId = Technician.Id;
}
private static bool CanCloseNever(this Job j, JobQueueJob IgnoreJobQueueJob = null)
{
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.Close))
return false;
if (j.ClosedDate.HasValue)
return false; // Job already Closed
return true; // Job already Closed
if (j.DeviceHeld.HasValue && !j.DeviceReturnedDate.HasValue)
return false; // Device not returned to User
return true; // Device not returned to User
if (j.WaitingForUserAction.HasValue)
return false; // Job waiting on User Action
return true; // Job waiting on User Action
if (IgnoreJobQueueJob == null)
{
if (j.JobQueues.Any(jqj => !jqj.RemovedDate.HasValue))
return true; // Job associated with a Job Queue
}
else
{
if (j.JobQueues.Any(jqj => jqj.Id != IgnoreJobQueueJob.Id && !jqj.RemovedDate.HasValue))
return true; // Job associated with a Job Queue
}
return false;
}
public static bool CanCloseNormally(this Job j)
{
if (j.CanCloseNever())
return false;
return j.CanCloseNormallyInternal();
}
private static bool CanCloseNormallyInternal(this Job j)
{
switch (j.JobTypeId)
{
case JobType.JobTypeIds.HWar:
@@ -374,36 +407,27 @@ namespace Disco.BI.Extensions
return true;
}
public static void OnClose(this Job j, User Technician)
{
if (!j.CanClose())
throw new InvalidOperationException("Close was Denied");
j.ClosedDate = DateTime.Now;
j.ClosedTechUserId = Technician.Id;
public static bool CanCloseJobNormallyAfterRemoved(this JobQueueJob jqj)
{
if (jqj.Job.CanCloseNever(jqj))
return false;
return jqj.Job.CanCloseNormallyInternal();
}
#endregion
#region Force Close
public static bool CanForceClose(this Job j)
public static bool CanCloseForced(this Job j)
{
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.ForceClose))
return false;
var canCloseNormally = j.CanClose();
if (canCloseNormally)
if (j.CanCloseNever())
return false;
// Check for Override
if (j.ClosedDate.HasValue)
return false; // Job already Closed
if (j.DeviceHeld.HasValue && !j.DeviceReturnedDate.HasValue)
return false; // Device not returned to User
if (j.WaitingForUserAction.HasValue)
return false; // Job waiting on User Action
if (j.CanCloseNormally())
return false;
switch (j.JobTypeId)
{
@@ -427,9 +451,9 @@ namespace Disco.BI.Extensions
return false;
}
public static void OnForceClose(this Job j, DiscoDataContext Database, User Technician, string Reason)
public static void OnCloseForced(this Job j, DiscoDataContext Database, User Technician, string Reason)
{
if (!j.CanForceClose())
if (!j.CanCloseForced())
throw new InvalidOperationException("Force Close was Denied");
// Write Log
-102
View File
@@ -44,108 +44,6 @@ namespace Disco.BI.Extensions
return ja;
}
public static Tuple<string, string> Status(this Job j)
{
var statusId = j.CalculateStatusId();
return new Tuple<string, string>(statusId, JobBI.Utilities.JobStatusDescription(statusId, j));
}
public static JobTableModel.JobTableItemModelIncludeStatus ToJobTableItemModelIncludeStatus(this Job j)
{
var i = new JobTableModel.JobTableItemModelIncludeStatus()
{
Id = j.Id,
OpenedDate = j.OpenedDate,
ClosedDate = j.ClosedDate,
TypeId = j.JobTypeId,
TypeDescription = j.JobType.Description,
Location = j.DeviceHeldLocation,
WaitingForUserAction = j.WaitingForUserAction,
DeviceReadyForReturn = j.DeviceReadyForReturn,
DeviceHeld = j.DeviceHeld,
DeviceReturnedDate = j.DeviceReturnedDate
};
if (j.Device != null)
{
i.DeviceSerialNumber = j.DeviceSerialNumber;
i.DeviceModelDescription = j.Device.DeviceModel.Description;
i.DeviceAddressId = j.Device.DeviceProfile.DefaultOrganisationAddress;
if (j.JobMetaWarranty != null)
{
i.JobMetaWarranty_ExternalReference = j.JobMetaWarranty.ExternalReference;
i.JobMetaWarranty_ExternalCompletedDate = j.JobMetaWarranty.ExternalCompletedDate;
i.JobMetaWarranty_ExternalName = j.JobMetaWarranty.ExternalName;
}
if (j.JobMetaNonWarranty != null)
{
i.JobMetaNonWarranty_RepairerLoggedDate = j.JobMetaNonWarranty.RepairerLoggedDate;
i.JobMetaNonWarranty_RepairerCompletedDate = j.JobMetaNonWarranty.RepairerCompletedDate;
i.JobMetaNonWarranty_AccountingChargeAddedDate = j.JobMetaNonWarranty.AccountingChargeAddedDate;
i.JobMetaNonWarranty_AccountingChargePaidDate = j.JobMetaNonWarranty.AccountingChargePaidDate;
i.JobMetaNonWarranty_AccountingChargeRequiredDate = j.JobMetaNonWarranty.AccountingChargeRequiredDate;
i.JobMetaNonWarranty_IsInsuranceClaim = j.JobMetaNonWarranty.IsInsuranceClaim;
i.JobMetaNonWarranty_RepairerName = j.JobMetaNonWarranty.RepairerName;
if (j.JobMetaInsurance != null)
{
i.JobMetaInsurance_ClaimFormSentDate = j.JobMetaInsurance.ClaimFormSentDate;
}
}
}
if (j.User != null)
{
i.UserId = j.UserId;
i.UserDisplayName = j.User.DisplayName;
}
if (j.OpenedTechUser != null)
{
i.OpenedTechUserId = j.OpenedTechUserId;
i.OpenedTechUserDisplayName = j.OpenedTechUser.DisplayName;
}
return i;
}
public static string CalculateStatusId(this Job j)
{
return j.ToJobTableItemModelIncludeStatus().CalculateStatusId();
}
public static string CalculateStatusId(this JobTableModel.JobTableItemModelIncludeStatus j)
{
if (j.ClosedDate.HasValue)
return Job.JobStatusIds.Closed;
if (j.TypeId == JobType.JobTypeIds.HWar)
{
if (!string.IsNullOrEmpty(j.JobMetaWarranty_ExternalReference) && !j.JobMetaWarranty_ExternalCompletedDate.HasValue)
return Job.JobStatusIds.AwaitingWarrantyRepair; // Job Logged - but not marked as completed
}
if (j.TypeId == JobType.JobTypeIds.HNWar)
{
if (j.JobMetaNonWarranty_RepairerLoggedDate.HasValue && !j.JobMetaNonWarranty_RepairerCompletedDate.HasValue)
return Job.JobStatusIds.AwaitingRepairs; // Repairs logged - but not complete
if (j.JobMetaNonWarranty_AccountingChargeAddedDate.HasValue && !j.JobMetaNonWarranty_AccountingChargePaidDate.HasValue)
return Job.JobStatusIds.AwaitingAccountingPayment; // Accounting Charge Added, but not paid
if (j.JobMetaNonWarranty_AccountingChargeRequiredDate.HasValue && (!j.JobMetaNonWarranty_AccountingChargePaidDate.HasValue || !j.JobMetaNonWarranty_AccountingChargeAddedDate.HasValue))
return Job.JobStatusIds.AwaitingAccountingCharge; // Accounting Charge Required, but not added or paid
if (j.JobMetaNonWarranty_RepairerLoggedDate.HasValue && j.JobMetaNonWarranty_IsInsuranceClaim.Value && !j.JobMetaInsurance_ClaimFormSentDate.HasValue)
return Job.JobStatusIds.AwaitingInsuranceProcessing; // Is insurance claim, but no Claim Form Sent
}
if (j.WaitingForUserAction.HasValue)
return Job.JobStatusIds.AwaitingUserAction; // Awaiting for User
if (j.DeviceReadyForReturn.HasValue && !j.DeviceReturnedDate.HasValue)
return Job.JobStatusIds.AwaitingDeviceReturn; // Device not returned to User
return Job.JobStatusIds.Open;
}
public static List<DocumentTemplate> AvailableDocumentTemplates(this Job j, DiscoDataContext Database, User User, DateTime TimeStamp)
{
var dts = Database.DocumentTemplates.Include("JobSubTypes")
@@ -0,0 +1,216 @@
using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Services.Authorization;
using Disco.Services.Jobs.JobQueues;
using Disco.Services.Users;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.BI.Extensions
{
public static class JobQueueActionExtensions
{
#region Edit Sla
public static bool CanEditSla(this JobQueueJob jqj)
{
if (jqj.RemovedDate.HasValue)
return false;
if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditAnySLA))
{
// Can edit ANY queue
return true;
}
else if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditOwnSLA))
{
// Can edit from OWN queue
return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jqj.JobQueueId);
}
else
{
return false;
}
}
public static void OnEditSla(this JobQueueJob jqj, DateTime? SlaExpiresDate)
{
if (!jqj.CanEditSla())
throw new InvalidOperationException("Editing job SLA for this queue is denied");
if (SlaExpiresDate.HasValue && jqj.AddedDate > SlaExpiresDate.Value)
throw new ArgumentException("The SLA Expires Date must be greater than the Added Date", "SLAExpiresDate");
jqj.SLAExpiresDate = SlaExpiresDate;
}
#endregion
#region Edit Priority
public static bool CanEditPriority(this JobQueueJob jqj)
{
if (jqj.RemovedDate.HasValue)
return false;
if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditAnyPriority))
{
// Can edit ANY queue
return true;
}
else if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditOwnPriority))
{
// Can edit from OWN queue
return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jqj.JobQueueId);
}
else
{
return false;
}
}
public static void OnEditPriority(this JobQueueJob jqj, JobQueuePriority Priority)
{
if (!jqj.CanEditPriority())
throw new InvalidOperationException("Editing job priority for this queue is denied");
jqj.Priority = Priority;
}
#endregion
#region Edit Comments
private static bool CanEditComments(this JobQueueJob jqj)
{
if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditAnyComments))
{
// Can edit ANY queue
return true;
}
else if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditOwnComments))
{
// Can edit from OWN queue
return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jqj.JobQueueId);
}
else
{
return false;
}
}
public static bool CanEditAddedComment(this JobQueueJob jqj)
{
return jqj.CanEditComments();
}
public static bool CanEditRemovedComment(this JobQueueJob jqj)
{
if (!jqj.RemovedDate.HasValue)
return false;
return jqj.CanEditComments();
}
public static void OnEditAddedComment(this JobQueueJob jqj, string AddedComment)
{
if (!jqj.CanEditAddedComment())
throw new InvalidOperationException("Editing job added comments for this queue is denied");
jqj.AddedComment = string.IsNullOrWhiteSpace(AddedComment) ? null : AddedComment.Trim();
}
public static void OnEditRemovedComment(this JobQueueJob jqj, string RemovedComment)
{
if (!jqj.CanEditRemovedComment())
throw new InvalidOperationException("Editing job removed comments for this queue is denied");
jqj.RemovedComment = string.IsNullOrWhiteSpace(RemovedComment) ? null : RemovedComment.Trim();
}
#endregion
#region Remove
public static bool CanRemove(this JobQueueJob jqj)
{
if (jqj.RemovedDate.HasValue)
return false;
if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.RemoveAnyQueues))
{
// Can remove from ANY queue
return true;
}
else if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.RemoveOwnQueues))
{
// Can remove from OWN queue
return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jqj.JobQueueId);
}
else
{
return false;
}
}
public static void OnRemove(this JobQueueJob jqj, User Technician, string Comment)
{
if (!jqj.CanRemove())
throw new InvalidOperationException("Removing job from queue is Denied");
jqj.RemovedDate = DateTime.Now;
jqj.RemovedUserId = Technician.Id;
jqj.RemovedComment = string.IsNullOrWhiteSpace(Comment) ? null : Comment.Trim();
}
#endregion
#region Add
public static bool CanAddQueues(this Job j)
{
// Job Closed?
if (j.ClosedDate.HasValue)
return false;
if (UserService.CurrentAuthorization.HasAny(Claims.Job.Actions.AddAnyQueues, Claims.Job.Actions.AddOwnQueues))
return true;
return false;
}
public static bool CanAddQueue(this Job j, JobQueue jq)
{
// Shortcut
if (!j.CanAddQueues())
return false;
// Already in Queue?
if (j.JobQueues.Count(jjq => !jjq.RemovedDate.HasValue && jjq.JobQueueId == jq.Id) > 0)
return false;
// Can add ANY queue
if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.AddAnyQueues))
return true;
// Can add OWN queue
if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.AddOwnQueues))
{
return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jq.Id);
}
return false;
}
public static JobQueueJob OnAddQueue(this Job j, DiscoDataContext Database, JobQueue jq, User Technician, string Comment, DateTime? SLAExpires, JobQueuePriority Priority)
{
if (!j.CanAddQueue(jq))
throw new InvalidOperationException("Adding job to queue is Denied");
if (SLAExpires.HasValue && SLAExpires.Value < DateTime.Now)
throw new ArgumentException("The SLA Date must be greater than the current time", "SLAExpires");
var jqj = new JobQueueJob()
{
JobQueueId = jq.Id,
JobId = j.Id,
AddedDate = DateTime.Now,
AddedUserId = Technician.Id,
AddedComment = string.IsNullOrWhiteSpace(Comment) ? null : Comment.Trim(),
SLAExpiresDate = SLAExpires,
Priority = Priority
};
Database.JobQueueJobs.Add(jqj);
return jqj;
}
#endregion
}
}
@@ -1,181 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Disco.Models.BI.Job;
using Disco.Models.Repository;
using Disco.Data.Repository;
using Disco.Services.Users;
using Disco.Services.Authorization;
namespace Disco.BI.Extensions
{
public static class JobTableExtensions
{
private static List<string> FilterAllowedTypes(AuthorizationToken Authorization)
{
if (!Authorization.HasAll(Claims.Job.Types.ShowHMisc, Claims.Job.Types.ShowHNWar, Claims.Job.Types.ShowHWar, Claims.Job.Types.ShowSApp, Claims.Job.Types.ShowSImg, Claims.Job.Types.ShowSOS, Claims.Job.Types.ShowUMgmt))
{
// Must Filter
List<string> allowedTypes = new List<string>(6);
if (Authorization.Has(Claims.Job.Types.ShowHMisc))
allowedTypes.Add(JobType.JobTypeIds.HMisc);
if (Authorization.Has(Claims.Job.Types.ShowHNWar))
allowedTypes.Add(JobType.JobTypeIds.HNWar);
if (Authorization.Has(Claims.Job.Types.ShowHWar))
allowedTypes.Add(JobType.JobTypeIds.HWar);
if (Authorization.Has(Claims.Job.Types.ShowSApp))
allowedTypes.Add(JobType.JobTypeIds.SApp);
if (Authorization.Has(Claims.Job.Types.ShowSImg))
allowedTypes.Add(JobType.JobTypeIds.SImg);
if (Authorization.Has(Claims.Job.Types.ShowSOS))
allowedTypes.Add(JobType.JobTypeIds.SOS);
if (Authorization.Has(Claims.Job.Types.ShowUMgmt))
allowedTypes.Add(JobType.JobTypeIds.UMgmt);
return allowedTypes;
}
return null;
}
public static IQueryable<Job> FilterPermissions(this JobTableModel model, IQueryable<Job> Jobs, AuthorizationToken Authorization)
{
var allowedTypes = FilterAllowedTypes(Authorization);
if (allowedTypes != null)
{
return Jobs.Where(j => allowedTypes.Contains(j.JobTypeId));
}
return Jobs;
}
public static List<JobTableModel.JobTableItemModel> PermissionsFiltered(this List<JobTableModel.JobTableItemModel> Items, AuthorizationToken Authorization)
{
if (Items != null && Items.Count > 0)
{
var allowedTypes = FilterAllowedTypes(Authorization);
if (allowedTypes != null)
{
return Items.Where(j => allowedTypes.Contains(j.TypeId)).ToList();
}
}
return Items;
}
public static List<JobTableModel.JobTableItemModel> DetermineItems(this JobTableModel model, DiscoDataContext Database, IQueryable<Job> Jobs)
{
List<JobTableModel.JobTableItemModel> items;
// Permissions
var auth = UserService.CurrentAuthorization;
if (!auth.HasAll(Claims.Job.Types.ShowHMisc, Claims.Job.Types.ShowHNWar, Claims.Job.Types.ShowHWar, Claims.Job.Types.ShowSApp, Claims.Job.Types.ShowSImg, Claims.Job.Types.ShowSOS, Claims.Job.Types.ShowUMgmt))
{
// Must Filter
List<string> allowedTypes = new List<string>(6);
if (auth.Has(Claims.Job.Types.ShowHMisc))
allowedTypes.Add(JobType.JobTypeIds.HMisc);
if (auth.Has(Claims.Job.Types.ShowHNWar))
allowedTypes.Add(JobType.JobTypeIds.HNWar);
if (auth.Has(Claims.Job.Types.ShowHWar))
allowedTypes.Add(JobType.JobTypeIds.HWar);
if (auth.Has(Claims.Job.Types.ShowSApp))
allowedTypes.Add(JobType.JobTypeIds.SApp);
if (auth.Has(Claims.Job.Types.ShowSImg))
allowedTypes.Add(JobType.JobTypeIds.SImg);
if (auth.Has(Claims.Job.Types.ShowSOS))
allowedTypes.Add(JobType.JobTypeIds.SOS);
if (auth.Has(Claims.Job.Types.ShowUMgmt))
allowedTypes.Add(JobType.JobTypeIds.UMgmt);
Jobs = Jobs.Where(j => allowedTypes.Contains(j.JobTypeId));
}
if (model.ShowStatus)
{
var jobItems = Jobs.Select(j => new JobTableModel.JobTableItemModelIncludeStatus()
{
Id = j.Id,
OpenedDate = j.OpenedDate,
ClosedDate = j.ClosedDate,
TypeId = j.JobTypeId,
TypeDescription = j.JobType.Description,
DeviceSerialNumber = j.Device.SerialNumber,
DeviceProfileId = j.Device.DeviceProfileId,
DeviceModelId = j.Device.DeviceModelId,
DeviceModelDescription = j.Device.DeviceModel.Description,
DeviceAddressId = j.Device.DeviceProfile.DefaultOrganisationAddress,
UserId = j.UserId,
UserDisplayName = j.User.DisplayName,
OpenedTechUserId = j.OpenedTechUserId,
OpenedTechUserDisplayName = j.OpenedTechUser.DisplayName,
Location = j.DeviceHeldLocation,
JobMetaWarranty_ExternalReference = j.JobMetaWarranty.ExternalReference,
JobMetaWarranty_ExternalCompletedDate = j.JobMetaWarranty.ExternalCompletedDate,
JobMetaNonWarranty_RepairerLoggedDate = j.JobMetaNonWarranty.RepairerLoggedDate,
JobMetaNonWarranty_RepairerCompletedDate = j.JobMetaNonWarranty.RepairerCompletedDate,
JobMetaNonWarranty_AccountingChargeAddedDate = j.JobMetaNonWarranty.AccountingChargeAddedDate,
JobMetaNonWarranty_AccountingChargePaidDate = j.JobMetaNonWarranty.AccountingChargePaidDate,
JobMetaNonWarranty_AccountingChargeRequiredDate = j.JobMetaNonWarranty.AccountingChargeRequiredDate,
JobMetaNonWarranty_IsInsuranceClaim = j.JobMetaNonWarranty.IsInsuranceClaim,
JobMetaInsurance_ClaimFormSentDate = j.JobMetaInsurance.ClaimFormSentDate,
WaitingForUserAction = j.WaitingForUserAction,
DeviceReadyForReturn = j.DeviceReadyForReturn,
DeviceHeld = j.DeviceHeld,
DeviceReturnedDate = j.DeviceReturnedDate,
JobMetaWarranty_ExternalName = j.JobMetaWarranty.ExternalName,
JobMetaNonWarranty_RepairerName = j.JobMetaNonWarranty.RepairerName
});
items = new List<JobTableModel.JobTableItemModel>();
foreach (var j in jobItems)
{
j.StatusId = j.CalculateStatusId();
j.StatusDescription = JobBI.Utilities.JobStatusDescription(j.StatusId, j);
items.Add(j);
}
}
else
{
items = Jobs.Select(j => new JobTableModel.JobTableItemModel()
{
Id = j.Id,
OpenedDate = j.OpenedDate,
ClosedDate = j.ClosedDate,
TypeId = j.JobTypeId,
TypeDescription = j.JobType.Description,
DeviceSerialNumber = j.Device.SerialNumber,
DeviceProfileId = j.Device.DeviceProfileId,
DeviceModelId = j.Device.DeviceModelId,
DeviceModelDescription = j.Device.DeviceModel.Description,
DeviceAddressId = j.Device.DeviceProfile.DefaultOrganisationAddress,
UserId = j.UserId,
UserDisplayName = j.User.DisplayName,
OpenedTechUserId = j.OpenedTechUserId,
OpenedTechUserDisplayName = j.OpenedTechUser.DisplayName,
Location = j.DeviceHeldLocation
}).ToList();
}
if (!model.ShowDeviceAddress.HasValue)
model.ShowDeviceAddress = Database.DiscoConfiguration.MultiSiteMode;
foreach (var j in items)
if (j.DeviceAddressId.HasValue)
j.DeviceAddress = Database.DiscoConfiguration.OrganisationAddresses.GetAddress(j.DeviceAddressId.Value).Name;
return items;
}
public static void Fill(this JobTableModel model, DiscoDataContext Database, IQueryable<Job> Jobs)
{
model.Items = model.DetermineItems(Database, Jobs);
}
}
}
-188
View File
@@ -1,188 +0,0 @@
using Disco.Data.Repository;
using Disco.Data.Repository.Monitor;
using Disco.Models.BI.Job;
using Disco.Models.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Disco.BI.Extensions;
using System.Reactive.Linq;
using Disco.Services.Users;
namespace Disco.BI.JobBI
{
using FilterFunc = Func<IQueryable<Job>, IQueryable<Job>>;
using SortFunc = Func<IEnumerable<Disco.Models.BI.Job.JobTableModel.JobTableItemModel>, IEnumerable<Disco.Models.BI.Job.JobTableModel.JobTableItemModel>>;
using Disco.Services.Logging;
public class ManagedJobList : JobTableModel, IDisposable
{
public string Name { get; set; }
public FilterFunc FilterFunction { get; set; }
public SortFunc SortFunction { get; set; }
private IDisposable unsubscribeToken;
private object updateLock = new object();
public override List<JobTableItemModel> Items
{
get
{
return base.Items.PermissionsFiltered(UserService.CurrentAuthorization);
}
set
{
throw new InvalidOperationException("Items cannot be manually set in a Managed Job List");
}
}
public ManagedJobList Initialize(DiscoDataContext Database)
{
// Can only Initialize once
if (base.Items != null)
return ReInitialize(Database);
lock (updateLock)
{
// Subscribe for Changes
// - Job (or Job Meta) Changes
// - Device Profile Address Changes (for multi-campus Schools)
// - Device Model Description Changes
// - Device's Profile or Model Changes
unsubscribeToken = RepositoryMonitor.StreamAfterCommit
.Where(n => n.EntityType == typeof(Job) ||
n.EntityType == typeof(JobMetaWarranty) ||
n.EntityType == typeof(JobMetaNonWarranty) ||
n.EntityType == typeof(JobMetaInsurance) ||
(n.EventType == RepositoryMonitorEventType.Modified && (
(n.EntityType == typeof(DeviceProfile) && n.ModifiedProperties.Contains("DefaultOrganisationAddress")) ||
(n.EntityType == typeof(DeviceModel) && n.ModifiedProperties.Contains("Description")) ||
(n.EntityType == typeof(Device) && n.ModifiedProperties.Contains("DeviceProfileId") || n.ModifiedProperties.Contains("DeviceModelId"))
)))
.Subscribe(JobNotification, NotificationError);
// Initially fill table
base.Items = this.SortFunction(this.DetermineItems(Database, this.FilterFunction(Database.Jobs))).ToList();
}
return this;
}
public ManagedJobList ReInitialize(DiscoDataContext Database)
{
return ReInitialize(Database, null, null);
}
public ManagedJobList ReInitialize(DiscoDataContext Database, FilterFunc FilterFunction)
{
return ReInitialize(Database, FilterFunction, null);
}
public ManagedJobList ReInitialize(DiscoDataContext Database, FilterFunc FilterFunction, SortFunc SortFunction)
{
if (Database == null)
throw new ArgumentNullException("Database");
lock (updateLock)
{
if (FilterFunction != null)
this.FilterFunction = FilterFunction;
if (SortFunction != null)
this.SortFunction = SortFunction;
base.Items = this.SortFunction(this.DetermineItems(Database, this.FilterFunction(Database.Jobs))).ToList();
}
return this;
}
private void NotificationError(Exception ex)
{
SystemLog.LogException(string.Format("Disco.BI.JobBI.ManagedJobList: [{0}]", this.Name), ex);
}
private void JobNotification(RepositoryMonitorEvent e)
{
List<int> jobIds = null;
JobTableItemModel[] existingItems = null;
if (e.EntityType == typeof(Job))
jobIds = new List<int>() { ((Job)e.Entity).Id };
else
if (e.EntityType == typeof(JobMetaWarranty))
jobIds = new List<int>() { ((JobMetaWarranty)e.Entity).JobId };
else
if (e.EntityType == typeof(JobMetaNonWarranty))
jobIds = new List<int>() { ((JobMetaNonWarranty)e.Entity).JobId };
else
if (e.EntityType == typeof(JobMetaInsurance))
jobIds = new List<int>() { ((JobMetaInsurance)e.Entity).JobId };
else
if (e.EntityType == typeof(DeviceProfile))
{
int deviceProfileId = ((DeviceProfile)e.Entity).Id;
existingItems = base.Items.Where(i => i.DeviceProfileId == deviceProfileId).ToArray();
}
else
if (e.EntityType == typeof(DeviceModel))
{
int deviceModelId = ((DeviceModel)e.Entity).Id;
existingItems = base.Items.Where(i => i.DeviceModelId == deviceModelId).ToArray();
}
else
if (e.EntityType == typeof(Device))
{
string deviceSerialNumber = ((Device)e.Entity).SerialNumber;
existingItems = base.Items.Where(i => i.DeviceSerialNumber == deviceSerialNumber).ToArray();
}
else
return; // Subscription should never reach
if (jobIds == null)
{
if (existingItems == null)
throw new InvalidOperationException("Notification algorithm didn't indicate any Jobs for update");
else
jobIds = existingItems.Select(i => i.Id).ToList();
}
if (jobIds.Count == 0)
return;
else
UpdateJobs(e.Database, jobIds, existingItems);
}
private void UpdateJobs(DiscoDataContext Database, List<int> jobIds, JobTableItemModel[] existingItems = null)
{
lock (updateLock)
{
// Check for existing items, if not handed them
if (existingItems == null)
existingItems = base.Items.Where(i => jobIds.Contains(i.Id)).ToArray();
var updatedItems = this.DetermineItems(Database, this.FilterFunction(Database.Jobs.Where(j => jobIds.Contains(j.Id))));
var refreshedList = base.Items.ToList();
// Remove Existing
if (existingItems.Length > 0)
foreach (var existingItem in existingItems)
refreshedList.Remove(existingItem);
// Add Updated Items
if (updatedItems.Count > 0)
foreach (var updatedItem in updatedItems)
refreshedList.Add(updatedItem);
// Reorder
base.Items = this.SortFunction(refreshedList).ToList();
}
}
public void Dispose()
{
if (unsubscribeToken != null)
{
unsubscribeToken.Dispose();
unsubscribeToken = null;
}
}
}
}
+4 -7
View File
@@ -1,11 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Disco.Models.BI.Job;
using Disco.Data.Repository;
using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.BI.Extensions;
using Disco.Models.Services.Jobs.JobLists;
using Disco.Services;
using System.Linq;
namespace Disco.BI.JobBI
{
+28 -78
View File
@@ -40,6 +40,34 @@ namespace Disco.BI.JobBI
Database.Jobs.Add(j);
// Job Queues
var queues = from st in subTypes
from jq in st.JobQueues
group st by jq into g
select new { queue = g.Key, subTypes = g };
foreach (var queue in queues)
{
var commentBuilder = new StringBuilder("Automatically added by:");
foreach (var subType in queue.subTypes)
{
commentBuilder.AppendLine();
commentBuilder.Append(subType.Description);
}
var jqj = new JobQueueJob()
{
JobQueueId = queue.queue.Id,
Job = j,
AddedDate = DateTime.Now,
AddedUserId = initialTech.Id,
AddedComment = commentBuilder.ToString(),
SLAExpiresDate = queue.queue.DefaultSLAExpiry.HasValue ? (DateTime?)DateTime.Now.AddMinutes(queue.queue.DefaultSLAExpiry.Value) : null,
Priority = JobQueuePriority.Normal
};
Database.JobQueueJobs.Add(jqj);
}
switch (type.Id)
{
case JobType.JobTypeIds.HWar:
@@ -89,83 +117,5 @@ namespace Disco.BI.JobBI
return j;
}
public static string JobStatusDescription(string StatusId, Job j = null)
{
switch (StatusId)
{
case Job.JobStatusIds.Open:
return "Open";
case Job.JobStatusIds.Closed:
return "Closed";
case Job.JobStatusIds.AwaitingWarrantyRepair:
if (j == null)
return "Awaiting Warranty Repair";
else
if (j.DeviceHeld.HasValue)
return string.Format("Awaiting Warranty Repair ({0})", j.JobMetaWarranty.ExternalName);
else
return string.Format("Awaiting Warranty Repair - Not Held ({0})", j.JobMetaWarranty.ExternalName);
case Job.JobStatusIds.AwaitingRepairs:
if (j == null)
return "Awaiting Repairs";
else
if (j.DeviceHeld.HasValue)
return string.Format("Awaiting Repairs ({0})", j.JobMetaNonWarranty.RepairerName);
else
return string.Format("Awaiting Repairs - Not Held ({0})", j.JobMetaNonWarranty.RepairerName);
case Job.JobStatusIds.AwaitingDeviceReturn:
return "Awaiting Device Return";
case Job.JobStatusIds.AwaitingUserAction:
return "Awaiting User Action";
case Job.JobStatusIds.AwaitingAccountingPayment:
return "Awaiting Accounting Payment";
case Job.JobStatusIds.AwaitingAccountingCharge:
return "Awaiting Accounting Charge";
case Job.JobStatusIds.AwaitingInsuranceProcessing:
return "Awaiting Insurance Processing";
default:
return "Unknown";
}
}
public static string JobStatusDescription(string StatusId, JobTableModel.JobTableItemModelIncludeStatus j = null)
{
switch (StatusId)
{
case Job.JobStatusIds.Open:
return "Open";
case Job.JobStatusIds.Closed:
return "Closed";
case Job.JobStatusIds.AwaitingWarrantyRepair:
if (j == null)
return "Awaiting Warranty Repair";
else
if (j.DeviceHeld.HasValue)
return string.Format("Awaiting Warranty Repair ({0})", j.JobMetaWarranty_ExternalName);
else
return string.Format("Awaiting Warranty Repair - Not Held ({0})", j.JobMetaWarranty_ExternalName);
case Job.JobStatusIds.AwaitingRepairs:
if (j == null)
return "Awaiting Repairs";
else
if (j.DeviceHeld.HasValue)
return string.Format("Awaiting Repairs ({0})", j.JobMetaNonWarranty_RepairerName);
else
return string.Format("Awaiting Repairs - Not Held ({0})", j.JobMetaNonWarranty_RepairerName);
case Job.JobStatusIds.AwaitingDeviceReturn:
return "Awaiting Device Return";
case Job.JobStatusIds.AwaitingUserAction:
return "Awaiting User Action";
case Job.JobStatusIds.AwaitingAccountingPayment:
return "Awaiting Accounting Payment";
case Job.JobStatusIds.AwaitingAccountingCharge:
return "Awaiting Accounting Charge";
case Job.JobStatusIds.AwaitingInsuranceProcessing:
return "Awaiting Insurance Processing";
default:
return "Unknown";
}
}
}
}