using Disco.Data.Repository; using Disco.Models.BI.Config; using Disco.Models.Repository; using Disco.Services.Authorization; using Disco.Services.Logging; using Disco.Services.Plugins; using Disco.Services.Plugins.Features.InsuranceProvider; using Disco.Services.Plugins.Features.RepairProvider; using Disco.Services.Plugins.Features.WarrantyProvider; using Disco.Services.Users; using System; using System.Collections.Generic; using System.Linq; using DiscoServicesJobs = Disco.Services.Interop.DiscoServices.Jobs; using PublishJobResult = Disco.Models.Services.Interop.DiscoServices.PublishJobResult; namespace Disco.Services { public static class JobActionExtensions { #region Create public static bool CanCreate() { if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.Create)) return false; if (!UserService.CurrentAuthorization.HasAny(Claims.Job.Types.CreateHMisc, Claims.Job.Types.CreateHNWar, Claims.Job.Types.CreateHWar, Claims.Job.Types.CreateSApp, Claims.Job.Types.CreateSImg, Claims.Job.Types.CreateSOS, Claims.Job.Types.CreateUMgmt)) return false; return true; } #endregion #region Device Held public static bool CanDeviceHeld(this Job j) { if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.DeviceHeld)) return false; return (!j.ClosedDate.HasValue) && (j.DeviceSerialNumber != null) && (!j.DeviceHeld.HasValue || j.DeviceReturnedDate.HasValue); } public static void OnDeviceHeld(this Job j, User Technician) { if (!j.CanDeviceHeld()) throw new InvalidOperationException("Holding Device was Denied"); j.DeviceHeld = DateTime.Now; j.DeviceHeldTechUserId = Technician.UserId; j.DeviceReadyForReturn = null; j.DeviceReadyForReturnTechUserId = null; j.DeviceReturnedDate = null; j.DeviceReturnedTechUserId = null; } #endregion #region Device Ready for Return public static bool CanDeviceReadyForReturn(this Job j) { if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.DeviceReadyForReturn)) return false; return (!j.ClosedDate.HasValue) && j.DeviceHeld.HasValue && !j.DeviceReadyForReturn.HasValue && !j.DeviceReturnedDate.HasValue; } public static void OnDeviceReadyForReturn(this Job j, DiscoDataContext Database, User Technician) { if (!j.CanDeviceReadyForReturn()) throw new InvalidOperationException("Device Ready for Return was Denied"); j.DeviceReadyForReturn = DateTime.Now; j.DeviceReadyForReturnTechUserId = Technician.UserId; // Evaluate OnDeviceReadyForReturnExpression Expression try { var result = j.EvaluateOnDeviceReadyForReturnExpression(Database); if (!string.IsNullOrWhiteSpace(result)) { var jl = new JobLog() { Job = j, TechUser = Technician, Timestamp = DateTime.Now, Comments = result }; Database.JobLogs.Add(jl); } } catch (Exception ex) { SystemLog.LogException("Job Expression - OnDeviceReadyForReturnExpression", ex); } } #endregion #region Device Returned public static bool CanDeviceReturned(this Job j) { if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.DeviceReturned)) return false; return (!j.ClosedDate.HasValue) && j.DeviceHeld.HasValue && !j.DeviceReturnedDate.HasValue; } public static void OnDeviceReturned(this Job j, User Technician) { if (!j.CanDeviceReturned()) throw new InvalidOperationException("Device Return was Denied"); j.DeviceReturnedDate = DateTime.Now; j.DeviceReturnedTechUserId = Technician.UserId; } #endregion #region Waiting For User Action public static bool CanWaitingForUserAction(this Job j) { if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.WaitingForUserAction)) return false; return !j.ClosedDate.HasValue && (j.UserId != null) && !j.WaitingForUserAction.HasValue; } public static void OnWaitingForUserAction(this Job j, DiscoDataContext Database, User Technician, string Reason) { if (!j.CanWaitingForUserAction()) throw new InvalidOperationException("Waiting for User Action was Denied"); j.WaitingForUserAction = DateTime.Now; // Write Log JobLog jobLog = new JobLog() { JobId = j.Id, TechUserId = Technician.UserId, Timestamp = DateTime.Now, Comments = $"# Waiting on User Action\r\n{(string.IsNullOrWhiteSpace(Reason) ? "" : Reason)}" }; Database.JobLogs.Add(jobLog); } #endregion #region Not Waiting For User Action public static bool CanNotWaitingForUserAction(this Job j) { if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.NotWaitingForUserAction)) return false; return j.WaitingForUserAction.HasValue; } public static void OnNotWaitingForUserAction(this Job j, DiscoDataContext Database, User Technician, string Resolution) { if (!j.CanNotWaitingForUserAction()) throw new InvalidOperationException("Not Waiting for User Action was Denied"); j.WaitingForUserAction = null; // Write Log JobLog jobLog = new JobLog() { JobId = j.Id, TechUserId = Technician.UserId, Timestamp = DateTime.Now, Comments = $"# User Action Resolved\r\n{(string.IsNullOrWhiteSpace(Resolution) ? "" : Resolution)}" }; Database.JobLogs.Add(jobLog); } #endregion #region Log Warranty public static bool CanLogWarranty(this Job j) { if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.LogWarranty)) return false; return !j.ClosedDate.HasValue && (j.DeviceSerialNumber != null) && j.JobTypeId == JobType.JobTypeIds.HWar && !j.JobMetaWarranty.ExternalLoggedDate.HasValue; } public static void OnLogWarranty(this Job j, DiscoDataContext Database, string FaultDescription, List SendAttachments, PluginFeatureManifest WarrantyProviderDefinition, OrganisationAddress Address, User TechUser, Dictionary WarrantyProviderProperties) { if (!j.CanLogWarranty()) throw new InvalidOperationException("Lodge Warranty was Denied"); PublishJobResult publishJobResult = null; using (WarrantyProviderFeature warrantyProvider = WarrantyProviderDefinition.CreateInstance()) { var warrantyProvider2 = warrantyProvider as WarrantyProvider2Feature; if (warrantyProvider2 == null && SendAttachments != null && SendAttachments.Count > 0) { publishJobResult = DiscoServicesJobs.Publish( Database, j, TechUser, warrantyProvider.WarrantyProviderId, null, FaultDescription, SendAttachments, AttachmentDataStoreExtensions.RepositoryFilename); if (!publishJobResult.Success) throw new Exception($"Disco ICT Online Services failed with the following message: {publishJobResult.ErrorMessage}"); if (string.IsNullOrWhiteSpace(FaultDescription)) FaultDescription = publishJobResult.PublishMessage; else FaultDescription = string.Concat(FaultDescription, Environment.NewLine, "___", Environment.NewLine, publishJobResult.PublishMessage); } string submitDescription; if (string.IsNullOrWhiteSpace(FaultDescription)) submitDescription = j.GenerateFaultDescriptionFooter(Database, WarrantyProviderDefinition); else submitDescription = string.Concat(FaultDescription, Environment.NewLine, Environment.NewLine, j.GenerateFaultDescriptionFooter(Database, WarrantyProviderDefinition)); string providerRef; if (warrantyProvider2 != null) providerRef = warrantyProvider2.SubmitJob(Database, j, Address, TechUser, FaultDescription, SendAttachments, WarrantyProviderProperties); else providerRef = warrantyProvider.SubmitJob(Database, j, Address, TechUser, submitDescription, WarrantyProviderProperties); j.JobMetaWarranty.ExternalLoggedDate = DateTime.Now; j.JobMetaWarranty.ExternalName = warrantyProvider.WarrantyProviderId; if (providerRef != null && providerRef.Length > 100) j.JobMetaWarranty.ExternalReference = providerRef.Substring(0, 100); else j.JobMetaWarranty.ExternalReference = providerRef; // Write Log JobLog jobLog = new JobLog() { JobId = j.Id, TechUserId = TechUser.UserId, Timestamp = DateTime.Now, Comments = $"# Warranty Claim Submitted\r\nProvider: **{warrantyProvider.Manifest.Name}**\r\nAddress: **{Address.Name}**\r\nReference: **{providerRef}**\r\n___\r\n```{FaultDescription}```" }; Database.JobLogs.Add(jobLog); if (publishJobResult != null) { try { DiscoServicesJobs.UpdateRecipientReference(Database, j, publishJobResult.Id, publishJobResult.Secret, j.JobMetaWarranty.ExternalReference); } catch (Exception) { } // Ignore Errors as this is not completely necessary } } } public static void OnLogWarranty(this Job j, DiscoDataContext Database, string FaultDescription, string ManualProviderName, string ManualProviderReference, OrganisationAddress Address, User TechUser) { if (!j.CanLogWarranty()) throw new InvalidOperationException("Lodge Warranty was Denied"); j.JobMetaWarranty.ExternalLoggedDate = DateTime.Now; j.JobMetaWarranty.ExternalName = ManualProviderName; if (ManualProviderReference != null && ManualProviderReference.Length > 100) j.JobMetaWarranty.ExternalReference = ManualProviderReference.Substring(0, 100); else j.JobMetaWarranty.ExternalReference = ManualProviderReference; // Write Log JobLog jobLog = new JobLog() { JobId = j.Id, TechUserId = TechUser.UserId, Timestamp = DateTime.Now, Comments = $"# Manual Warranty Claim Submitted\r\nProvider: **{ManualProviderName}**\r\nAddress: **{Address.Name}**\r\nReference: **{ManualProviderReference ?? ""}**\r\n___\r\n```{FaultDescription}```" }; Database.JobLogs.Add(jobLog); } #endregion #region Convert HWar to HNWar public static bool CanConvertHWarToHNWar(this Job j) { if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.ConvertHWarToHNWar)) return false; return !j.ClosedDate.HasValue && (j.DeviceSerialNumber != null) && j.JobTypeId == JobType.JobTypeIds.HWar && string.IsNullOrEmpty(j.JobMetaWarranty.ExternalReference); } public static void OnConvertHWarToHNWar(this Job j, DiscoDataContext Database) { if (!j.CanConvertHWarToHNWar()) throw new InvalidOperationException("Convert HWar to HNWar was Denied"); var techUser = UserService.CurrentUser; // Remove JobMetaWarranty if (j.JobMetaWarranty != null) Database.JobMetaWarranties.Remove(j.JobMetaWarranty); // Add JobMetaNonWarranty var metaHNWar = new JobMetaNonWarranty() { Job = j }; Database.JobMetaNonWarranties.Add(metaHNWar); // Swap Job Sub Types List jobSubTypes = j.JobSubTypes.Select(jst => jst.Id).ToList(); j.JobSubTypes.Clear(); foreach (var jst in Database.JobSubTypes.Where(i => i.JobTypeId == JobType.JobTypeIds.HNWar && jobSubTypes.Contains(i.Id))) j.JobSubTypes.Add(jst); // Add Components var components = Database.DeviceComponents.Include("JobSubTypes").Where(c => !c.DeviceModelId.HasValue || c.DeviceModelId == j.Device.DeviceModelId); var jobComponents = new List(); foreach (var component in components) { if (component.JobSubTypes.Count == 0) { jobComponents.Add(component); } else { foreach (var st in component.JobSubTypes) { foreach (var jst in j.JobSubTypes) { if (st.JobTypeId == jst.JobTypeId && st.Id == jst.Id) { jobComponents.Add(component); break; } } if (jobComponents.Contains(component)) break; } } } foreach (var component in jobComponents) { Database.JobComponents.Add(new JobComponent() { Job = j, TechUserId = techUser.UserId, Cost = component.Cost, Description = component.Description }); } // Write Log JobLog jobLog = new JobLog() { JobId = j.Id, TechUserId = techUser.UserId, Timestamp = DateTime.Now, Comments = $"# Job Type Converted\r\nFrom: **{Database.JobTypes.Find(JobType.JobTypeIds.HWar)}**\r\nTo: **{Database.JobTypes.Find(JobType.JobTypeIds.HNWar)}**" }; Database.JobLogs.Add(jobLog); j.JobTypeId = JobType.JobTypeIds.HNWar; } #endregion #region Warranty Completed public static bool CanWarrantyCompleted(this Job j) { return (j.JobTypeId == JobType.JobTypeIds.HWar) && j.JobMetaWarranty.ExternalLoggedDate.HasValue && !j.JobMetaWarranty.ExternalCompletedDate.HasValue; } public static void OnWarrantyCompleted(this Job j) { if (!j.CanWarrantyCompleted()) throw new InvalidOperationException("Warranty Completed was Denied"); j.JobMetaWarranty.ExternalCompletedDate = DateTime.Now; } #endregion #region Insurance Claim Form Sent [Obsolete("Use Log Insurance instead")] public static bool CanInsuranceClaimFormSent(this Job j) { if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.NonWarrantyProperties.InsuranceClaimFormSent)) return false; return (j.JobTypeId == JobType.JobTypeIds.HNWar) && j.JobMetaNonWarranty.IsInsuranceClaim && !j.JobMetaInsurance.ClaimFormSentDate.HasValue; } [Obsolete("Use Log Insurance instead")] public static void OnInsuranceClaimFormSent(this Job j) { if (!j.CanInsuranceClaimFormSent()) throw new InvalidOperationException("Insurance Claim Form Sent was Denied"); var techUser = UserService.CurrentUser; j.JobMetaInsurance.ClaimFormSentDate = DateTime.Now; j.JobMetaInsurance.ClaimFormSentUserId = techUser.UserId; } #endregion #region Log Repair public static bool CanLogRepair(this Job j) { if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.LogRepair)) return false; return (j.JobTypeId == JobType.JobTypeIds.HNWar) && (j.DeviceSerialNumber != null) && !j.JobMetaNonWarranty.RepairerLoggedDate.HasValue && !j.JobMetaNonWarranty.RepairerCompletedDate.HasValue; } public static void OnLogRepair(this Job j, DiscoDataContext Database, string RepairDescription, List SendAttachments, PluginFeatureManifest RepairProviderDefinition, OrganisationAddress Address, User TechUser, Dictionary RepairProviderProperties) { if (!j.CanLogRepair()) throw new InvalidOperationException("Lodge Repair was Denied"); PublishJobResult publishJobResult = null; using (RepairProviderFeature repairProvider = RepairProviderDefinition.CreateInstance()) { var repairProvider2 = repairProvider as RepairProvider2Feature; if (repairProvider2 == null && SendAttachments != null && SendAttachments.Count > 0) { publishJobResult = DiscoServicesJobs.Publish( Database, j, TechUser, repairProvider.ProviderId, null, RepairDescription, SendAttachments, AttachmentDataStoreExtensions.RepositoryFilename); if (!publishJobResult.Success) throw new Exception($"Disco ICT Online Services failed with the following message: {publishJobResult.ErrorMessage}"); if (string.IsNullOrWhiteSpace(RepairDescription)) RepairDescription = publishJobResult.PublishMessage; else RepairDescription = string.Concat(RepairDescription, Environment.NewLine, "___", Environment.NewLine, publishJobResult.PublishMessage); } string submitDescription; if (string.IsNullOrWhiteSpace(RepairDescription)) submitDescription = j.GenerateFaultDescriptionFooter(Database, RepairProviderDefinition); else submitDescription = string.Concat(RepairDescription, Environment.NewLine, Environment.NewLine, j.GenerateFaultDescriptionFooter(Database, RepairProviderDefinition)); string providerRef; if (repairProvider2 != null) providerRef = repairProvider2.SubmitJob(Database, j, Address, TechUser, submitDescription, SendAttachments, RepairProviderProperties); else providerRef = repairProvider.SubmitJob(Database, j, Address, TechUser, submitDescription, RepairProviderProperties); j.JobMetaNonWarranty.RepairerLoggedDate = DateTime.Now; j.JobMetaNonWarranty.RepairerName = repairProvider.ProviderId; if (providerRef != null && providerRef.Length > 100) j.JobMetaNonWarranty.RepairerReference = providerRef.Substring(0, 100); else j.JobMetaNonWarranty.RepairerReference = providerRef; // Write Log JobLog jobLog = new JobLog() { JobId = j.Id, TechUserId = TechUser.UserId, Timestamp = DateTime.Now, Comments = $"# Repair Request Submitted\r\nProvider: **{repairProvider.Manifest.Name}**\r\nAddress: **{Address.Name}**\r\nReference: **{providerRef}**\r\n___\r\n```{RepairDescription}```" }; Database.JobLogs.Add(jobLog); if (publishJobResult != null) { try { DiscoServicesJobs.UpdateRecipientReference(Database, j, publishJobResult.Id, publishJobResult.Secret, j.JobMetaNonWarranty.RepairerReference); } catch (Exception) { } // Ignore Errors as this is not completely necessary } } } public static void OnLogRepair(this Job j, DiscoDataContext Database, string FaultDescription, string ManualProviderName, string ManualProviderReference, OrganisationAddress Address, User TechUser) { if (!j.CanLogRepair()) throw new InvalidOperationException("Lodge Repair was Denied"); j.JobMetaNonWarranty.RepairerLoggedDate = DateTime.Now; j.JobMetaNonWarranty.RepairerName = ManualProviderName; if (ManualProviderReference != null && ManualProviderReference.Length > 100) j.JobMetaNonWarranty.RepairerReference = ManualProviderReference.Substring(0, 100); else j.JobMetaNonWarranty.RepairerReference = ManualProviderReference; // Write Log JobLog jobLog = new JobLog() { JobId = j.Id, TechUserId = TechUser.UserId, Timestamp = DateTime.Now, Comments = $"# Manual Repair Request Submitted\r\nProvider: **{ManualProviderName}**\r\nAddress: **{Address.Name}**\r\nReference: **{ManualProviderReference ?? ""}**\r\n___\r\n```{FaultDescription}```" }; Database.JobLogs.Add(jobLog); } #endregion #region Repair Complete public static bool CanRepairComplete(this Job j) { if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.NonWarrantyProperties.RepairerCompletedDate)) return false; return (j.JobTypeId == JobType.JobTypeIds.HNWar) && j.JobMetaNonWarranty.RepairerLoggedDate.HasValue && !j.JobMetaNonWarranty.RepairerCompletedDate.HasValue; } public static void OnRepairComplete(this Job j) { if (!j.CanRepairComplete()) throw new InvalidOperationException("Repair Complete was Denied"); j.JobMetaNonWarranty.RepairerCompletedDate = DateTime.Now; } #endregion #region Log Insurance public static bool CanLogInsurance(this Job j) { if (!UserService.CurrentAuthorization.HasAny(Claims.Job.Actions.LogInsurance, Claims.Job.Properties.NonWarrantyProperties.InsuranceClaimFormSent)) return false; return j.JobTypeId == JobType.JobTypeIds.HNWar && j.DeviceSerialNumber != null && j.JobMetaNonWarranty.IsInsuranceClaim && !j.JobMetaInsurance.ClaimFormSentDate.HasValue; } public static void OnLogInsurance(this Job j, DiscoDataContext database, List attachments, PluginFeatureManifest providerDefinition, OrganisationAddress address, User techUser, Dictionary providerProperties) { if (!j.CanLogInsurance()) throw new InvalidOperationException("Lodge Insurance was Denied"); using (var provider = providerDefinition.CreateInstance()) { var providerRef = provider.SubmitJob(database, j, address, techUser, attachments, providerProperties); j.JobMetaInsurance.Insurer = provider.ProviderId; j.JobMetaInsurance.ClaimFormSentDate = DateTime.Now; j.JobMetaInsurance.ClaimFormSentUserId = techUser.UserId; if (providerRef != null && providerRef.Length > 200) j.JobMetaInsurance.InsurerReference = providerRef.Substring(0, 200); else j.JobMetaInsurance.InsurerReference = providerRef; // Write Log var jobLog = new JobLog() { JobId = j.Id, TechUserId = techUser.UserId, Timestamp = DateTime.Now, Comments = $"# Insurance Claim Submitted\r\nProvider: **{provider.Manifest.Name}**\r\nAddress: **{address.Name}**\r\nReference: **{providerRef}**", }; database.JobLogs.Add(jobLog); } } public static void OnLogInsurance(this Job j, DiscoDataContext database, string manualProviderName, string manualProviderReference, OrganisationAddress address, User techUser) { if (!j.CanLogInsurance()) throw new InvalidOperationException("Lodge Insurance was Denied"); j.JobMetaInsurance.Insurer = manualProviderName; j.JobMetaInsurance.ClaimFormSentDate = DateTime.Now; j.JobMetaInsurance.ClaimFormSentUserId = techUser.UserId; if (manualProviderReference != null && manualProviderReference.Length > 200) j.JobMetaInsurance.InsurerReference = manualProviderReference.Substring(0, 200); else j.JobMetaInsurance.InsurerReference = manualProviderReference; // Write Log JobLog jobLog = new JobLog() { JobId = j.Id, TechUserId = techUser.UserId, Timestamp = DateTime.Now, Comments = $"# Manual Insurance Request Submitted\r\nProvider: **{manualProviderName}**\r\nAddress: **{address.Name}**\r\nReference: **{manualProviderReference ?? ""}**", }; database.JobLogs.Add(jobLog); } #endregion #region Close public static void OnCloseNormally(this Job j, DiscoDataContext Database, User Technician) { if (!j.CanCloseNormally()) throw new InvalidOperationException("Close was Denied"); j.ClosedDate = DateTime.Now; j.ClosedTechUserId = Technician.UserId; j.ClosedTechUser = Technician; // Evaluate OnClose Expression try { var onCloseResult = j.EvaluateOnCloseExpression(Database); if (!string.IsNullOrWhiteSpace(onCloseResult)) { var jl = new JobLog() { Job = j, TechUser = Technician, Timestamp = DateTime.Now, Comments = onCloseResult }; Database.JobLogs.Add(jl); } } catch (Exception ex) { SystemLog.LogException("Job Expression - OnCloseExpression", ex); } } private static bool CanCloseNever(this Job j, JobQueueJob IgnoreJobQueueJob = null) { if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.Close)) return true; if (j.ClosedDate.HasValue) return true; // Job already Closed if (j.DeviceHeld.HasValue && !j.DeviceReturnedDate.HasValue) return true; // Device not returned to User if (j.WaitingForUserAction.HasValue) return true; // Job waiting on User Action if (j.JobQueues != null) { 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: if (!string.IsNullOrEmpty(j.JobMetaWarranty.ExternalReference) && !j.JobMetaWarranty.ExternalCompletedDate.HasValue) return false; // Job Logged (Warranty) but not completed break; case JobType.JobTypeIds.HNWar: if (j.JobMetaNonWarranty.RepairerLoggedDate.HasValue && !j.JobMetaNonWarranty.RepairerCompletedDate.HasValue) return false; // Job Logged (Repair) but not completed if (j.JobMetaNonWarranty.AccountingChargeRequiredDate.HasValue && !j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue) return false; // Accounting Charge Required, but not added if ((j.JobMetaNonWarranty.AccountingChargeRequiredDate.HasValue || j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue) && !j.JobMetaNonWarranty.AccountingChargePaidDate.HasValue) return false; // Accounting Charge Required or Added, but not paid if (j.JobMetaNonWarranty.IsInsuranceClaim && !j.JobMetaInsurance.ClaimFormSentDate.HasValue) return false; // Is Insurance Claim, but claim form not sent break; } return true; } 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 CanCloseForced(this Job j) { return CanCloseForced(j, out _); } public static bool CanCloseForced(this Job j, out List Reasons) { Reasons = null; if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.ForceClose)) return false; if (j.CanCloseNever()) return false; if (j.CanCloseNormally()) return false; Reasons = new List(); switch (j.JobTypeId) { case JobType.JobTypeIds.HWar: if (!string.IsNullOrEmpty(j.JobMetaWarranty.ExternalReference) && !j.JobMetaWarranty.ExternalCompletedDate.HasValue) Reasons.Add("Warranty Job Not Completed"); // Job Logged (Warranty) but not completed break; case JobType.JobTypeIds.HNWar: if (j.JobMetaNonWarranty.RepairerLoggedDate.HasValue && !j.JobMetaNonWarranty.RepairerCompletedDate.HasValue) Reasons.Add("Repair Job Not Completed"); // Job Logged (Repair) but not completed if (j.JobMetaNonWarranty.AccountingChargeRequiredDate.HasValue && (!j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue && !j.JobMetaNonWarranty.AccountingChargePaidDate.HasValue)) Reasons.Add("Accounting Charge Required But Not Added Or Paid"); // Accounting Charge Required, but not added or paid else if (j.JobMetaNonWarranty.AccountingChargeRequiredDate.HasValue && !j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue) Reasons.Add("Accounting Charge Required But Not Added"); // Accounting Charge Required, but not added else if (j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue && !j.JobMetaNonWarranty.AccountingChargePaidDate.HasValue) Reasons.Add("Accounting Charge Added But Not Paid"); // Accounting Charge Added, but not paid else if (j.JobMetaNonWarranty.AccountingChargeRequiredDate.HasValue && !j.JobMetaNonWarranty.AccountingChargePaidDate.HasValue) Reasons.Add("Accounting Charge Required But Not Paid"); // Accounting Charge Required, but not paid if (j.JobMetaNonWarranty.IsInsuranceClaim && !j.JobMetaInsurance.ClaimFormSentDate.HasValue) Reasons.Add("Insurance Claim Form Not Sent"); // Is Insurance Claim, but claim form not sent break; } return (Reasons.Count > 0); } public static void OnCloseForced(this Job j, DiscoDataContext Database, User Technician, string Reason) { if (!j.CanCloseForced()) throw new InvalidOperationException("Force Close was Denied"); // Write Log JobLog jobLog = new JobLog() { JobId = j.Id, TechUserId = Technician.UserId, Timestamp = DateTime.Now, Comments = $@"## Job Forcibly Closed {(string.IsNullOrWhiteSpace(Reason) ? "" : Reason)}" }; Database.JobLogs.Add(jobLog); j.ClosedDate = DateTime.Now; j.ClosedTechUserId = Technician.UserId; j.ClosedTechUser = Technician; // Evaluate OnClose Expression try { var onCloseResult = j.EvaluateOnCloseExpression(Database); if (!string.IsNullOrWhiteSpace(onCloseResult)) { var jl = new JobLog() { Job = j, TechUser = Technician, Timestamp = DateTime.Now, Comments = onCloseResult }; Database.JobLogs.Add(jl); } } catch (Exception ex) { SystemLog.LogException("Job Expression - OnCloseExpression", ex); } } #endregion #region Reopen public static bool CanReopen(this Job j) { if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.Reopen)) return false; return j.ClosedDate.HasValue; } public static void OnReopen(this Job j, DiscoDataContext database, User technician) { if (!j.CanReopen()) throw new InvalidOperationException("Reopen was Denied"); var log = new JobLog() { JobId = j.Id, TechUserId = technician.UserId, Timestamp = DateTime.Now, Comments = $@"## Job Re-Opened Previously Closed by {j.ClosedTechUser.DisplayName} [`@{j.ClosedTechUser.FriendlyId()}`] at `{j.ClosedDate:yyyy-MM-dd HH:mm}`.", }; database.JobLogs.Add(log); j.ClosedDate = null; j.ClosedTechUserId = null; } #endregion #region Delete public static bool CanDelete(this Job j) { if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.Delete)) return false; return j.ClosedDate.HasValue; } public static void OnDelete(this Job j, DiscoDataContext Database) { // Job Sub Types j.JobSubTypes.Clear(); // Job Attachments foreach (var ja in j.JobAttachments.ToArray()) ja.OnDelete(Database); j.JobAttachments.Clear(); // Job Components foreach (var jc in j.JobComponents.ToArray()) Database.JobComponents.Remove(jc); j.JobComponents.Clear(); // Job Queue Jobs foreach (var jqj in j.JobQueues.ToArray()) Database.JobQueueJobs.Remove(jqj); j.JobQueues.Clear(); // Job Logs foreach (var jl in j.JobLogs.ToArray()) Database.JobLogs.Remove(jl); j.JobLogs.Clear(); // Job Meta if (j.JobMetaInsurance != null) { Database.JobMetaInsurances.Remove(j.JobMetaInsurance); j.JobMetaInsurance = null; } if (j.JobMetaNonWarranty != null) { Database.JobMetaNonWarranties.Remove(j.JobMetaNonWarranty); j.JobMetaNonWarranty = null; } if (j.JobMetaWarranty != null) { Database.JobMetaWarranties.Remove(j.JobMetaWarranty); j.JobMetaWarranty = null; } // Job Database.Jobs.Remove(j); } #endregion } }