///<summary>Efficiently queries DB to fill all in memory lists for all jobs passed in.</summary> public static void FillInMemoryLists(List <Job> listJobsAll) { //No need for remoting call here. List <long> jobNums = listJobsAll.Select(x => x.JobNum).ToList(); Dictionary <long, List <JobLink> > listJobLinksAll = JobLinks.GetJobLinksForJobs(jobNums).GroupBy(x => x.JobNum).ToDictionary(x => x.Key, x => x.ToList()); Dictionary <long, List <JobNote> > listJobNotesAll = JobNotes.GetJobNotesForJobs(jobNums).GroupBy(x => x.JobNum).ToDictionary(x => x.Key, x => x.ToList()); Dictionary <long, List <JobReview> > listJobReviewsAll = JobReviews.GetJobReviewsForJobs(jobNums).GroupBy(x => x.JobNum).ToDictionary(x => x.Key, x => x.ToList()); Dictionary <long, List <JobQuote> > listJobQuotesAll = JobQuotes.GetJobQuotesForJobs(jobNums).GroupBy(x => x.JobNum).ToDictionary(x => x.Key, x => x.ToList()); Dictionary <long, List <JobLog> > listJobLogsAll = JobLogs.GetJobLogsForJobs(jobNums).GroupBy(x => x.JobNum).ToDictionary(x => x.Key, x => x.ToList()); for (int i = 0; i < listJobsAll.Count; i++) { Job job = listJobsAll[i]; if (!listJobLinksAll.TryGetValue(job.JobNum, out job.ListJobLinks)) { job.ListJobLinks = new List <JobLink>(); //empty list if not found } if (!listJobNotesAll.TryGetValue(job.JobNum, out job.ListJobNotes)) { job.ListJobNotes = new List <JobNote>(); //empty list if not found } if (!listJobReviewsAll.TryGetValue(job.JobNum, out job.ListJobReviews)) { job.ListJobReviews = new List <JobReview>(); //empty list if not found } if (!listJobQuotesAll.TryGetValue(job.JobNum, out job.ListJobQuotes)) { job.ListJobQuotes = new List <JobQuote>(); //empty list if not found } if (!listJobLogsAll.TryGetValue(job.JobNum, out job.ListJobLogs)) { job.ListJobLogs = new List <JobLog>(); //empty list if not found } } }
public static JobLog MakeLogEntryForNote(Job job, JobNote jobNoteNew, JobNote jobNoteOld) { string note = ""; if (jobNoteNew == null) { note = "Discussion note by user: "******" on " + jobNoteOld.DateTimeNote.ToString() + " was deleted.\r\nMessage Text:\r\n" + jobNoteOld.Note; } else { note = "Discussion note by user: "******" on " + jobNoteOld.DateTimeNote.ToString() + " was edited."; } JobLog jobLog = new JobLog() { JobNum = job.JobNum, UserNumChanged = Security.CurUser.UserNum, UserNumExpert = job.UserNumExpert, UserNumEngineer = job.UserNumEngineer, Title = job.Title, Description = note, TimeEstimate = TimeSpan.FromHours(job.HoursEstimate) }; JobLogs.Insert(jobLog); return(JobLogs.GetOne(jobLog.JobLogNum)); //to get new timestamp. }
///<summary>Will return null if no changes were made.</summary> public static bool MakeLogEntryForEstimateChange(Job jobNew, Job jobOld, string note) { JobLog jobLog = new JobLog() { JobNum = jobNew.JobNum, UserNumChanged = Security.CurUser.UserNum, UserNumExpert = jobNew.UserNumExpert, UserNumEngineer = jobNew.UserNumEngineer, Title = jobNew.Title, Description = "", TimeEstimate = jobNew.TimeEstimateConcept + jobNew.TimeEstimateWriteup + jobNew.TimeEstimateDevelopment + jobNew.TimeEstimateReview + jobNew.TimeEstimateReview }; //Add review twice if (jobOld.HoursEstimateConcept != jobNew.HoursEstimateConcept) { if (!string.IsNullOrEmpty(jobLog.Description)) { jobLog.Description += "\r\n"; } jobLog.Description += "Concept Estimate Changed From " + jobOld.HoursEstimateConcept + " hours To " + jobNew.HoursEstimateConcept + " hours."; } if (jobOld.HoursEstimateWriteup != jobNew.HoursEstimateWriteup) { if (!string.IsNullOrEmpty(jobLog.Description)) { jobLog.Description += "\r\n"; } jobLog.Description += "Writeup Estimate Changed From " + jobOld.HoursEstimateWriteup + " hours To " + jobNew.HoursEstimateWriteup + " hours."; } if (jobOld.HoursEstimateDevelopment != jobNew.HoursEstimateDevelopment) { if (!string.IsNullOrEmpty(jobLog.Description)) { jobLog.Description += "\r\n"; } jobLog.Description += "Development Estimate Changed From " + jobOld.HoursEstimateDevelopment + " hours To " + jobNew.HoursEstimateDevelopment + " hours."; } if (jobOld.HoursEstimateReview != jobNew.HoursEstimateReview) { if (!string.IsNullOrEmpty(jobLog.Description)) { jobLog.Description += "\r\n"; } jobLog.Description += "Review Estimate Changed From " + jobOld.HoursEstimateReview + " hours To " + jobNew.HoursEstimateReview + " hours."; } if (!String.IsNullOrEmpty(note)) { jobLog.Description += "\r\nReason: " + note; } if (string.IsNullOrEmpty(jobLog.Description)) { return(false); } JobLogs.Insert(jobLog); return(true); }
public static JobLog MakeLogEntryForView(Job job) { JobLog jobLog = new JobLog() { JobNum = job.JobNum, UserNumChanged = Security.CurUser.UserNum, UserNumExpert = job.UserNumExpert, UserNumEngineer = job.UserNumEngineer, Title = job.Title, Description = "Job Viewed" }; JobLogs.Insert(jobLog); return(JobLogs.GetOne(jobLog.JobLogNum)); //to get new timestamp. }
public static JobLog MakeLogEntryForTitleChange(Job job, string oldTitle, string newTitle) { JobLog jobLog = new JobLog() { JobNum = job.JobNum, UserNumChanged = Security.CurUser.UserNum, UserNumExpert = job.UserNumExpert, UserNumEngineer = job.UserNumEngineer, Title = newTitle, Description = "Job Title Changed From\r\n" + oldTitle + "\r\nTo\r\n" + newTitle + "." }; JobLogs.Insert(jobLog); return(JobLogs.GetOne(jobLog.JobLogNum)); //to get new timestamp. }
public static JobLog MakeLogEntryForEstimateChange(Job job, double oldHours, double newHours) { JobLog jobLog = new JobLog() { JobNum = job.JobNum, UserNumChanged = Security.CurUser.UserNum, UserNumExpert = job.UserNumExpert, UserNumEngineer = job.UserNumEngineer, Title = job.Title, Description = "Job Estimate Changed From " + oldHours + " hours To " + newHours + " hours." }; JobLogs.Insert(jobLog); return(JobLogs.GetOne(jobLog.JobLogNum)); //to get new timestamp. }
public static JobLog MakeLogEntryForSaveCommit(Job job) { JobLog jobLog = new JobLog() { JobNum = job.JobNum, UserNumChanged = Security.CurUser.UserNum, UserNumExpert = job.UserNumExpert, UserNumEngineer = job.UserNumEngineer, Title = job.Title, Description = "Job Save Committed", TimeEstimate = TimeSpan.FromHours(job.HoursEstimate) }; JobLogs.Insert(jobLog); return(JobLogs.GetOne(jobLog.JobLogNum)); //to get new timestamp. }
public static JobLog MakeLogEntryForActive(Job job, long userNum, bool isActive) { string note = $@"Job was set to {(isActive?"active":"inactive")}"; JobLog jobLog = new JobLog() { JobNum = job.JobNum, UserNumChanged = Security.CurUser.UserNum, UserNumExpert = job.UserNumExpert, UserNumEngineer = job.UserNumEngineer, Title = job.Title, Description = note, TimeEstimate = TimeSpan.FromHours(job.HoursEstimate) }; JobLogs.Insert(jobLog); return(JobLogs.GetOne(jobLog.JobLogNum)); //to get new timestamp. }
public static JobLog MakeLogEntryForProject(Job jobNew, Job jobOld) { string note = $@"Job Project was manually changed from {jobOld.PatternReviewProject.ToString()} to {jobNew.PatternReviewProject.ToString()}."; JobLog jobLog = new JobLog() { JobNum = jobOld.JobNum, UserNumChanged = Security.CurUser.UserNum, UserNumExpert = jobOld.UserNumExpert, UserNumEngineer = jobOld.UserNumEngineer, Title = jobOld.Title, Description = note, TimeEstimate = TimeSpan.FromHours(jobNew.HoursEstimate) }; JobLogs.Insert(jobLog); JobNotifications.UpsertAllNotifications(jobNew, Security.CurUser.UserNum, JobNotificationChanges.PhaseChange); return(JobLogs.GetOne(jobLog.JobLogNum)); //to get new timestamp. }
///<summary>You must surround with a try-catch when calling this method. Deletes one job from the database. ///Also deletes all JobLinks, Job Events, and Job Notes associated with the job. Jobs that have reviews or quotes on them may not be deleted and will throw an exception.</summary> public static void Delete(long jobNum) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(), jobNum); return; } if (JobReviews.GetForJob(jobNum).Count > 0 || JobQuotes.GetForJob(jobNum).Count > 0) { throw new Exception(Lans.g("Jobs", "Not allowed to delete a job that has attached reviews or quotes. Set the status to deleted instead.")); //The exception is caught in FormJobEdit. } //JobReviews.DeleteForJob(jobNum);//do not delete, blocked above //JobQuotes.DeleteForJob(jobNum);//do not delete, blocked above JobLinks.DeleteForJob(jobNum); JobLogs.DeleteForJob(jobNum); JobNotes.DeleteForJob(jobNum); Crud.JobCrud.Delete(jobNum); //Finally, delete the job itself. }
public static JobLog MakeLogEntryForCategory(Job jobNew, Job jobOld) { string note = "Job Category was changed from " + jobOld.Category.ToString() + " to " + jobNew.Category.ToString() + "."; JobLog jobLog = new JobLog() { JobNum = jobOld.JobNum, UserNumChanged = Security.CurUser.UserNum, UserNumExpert = jobOld.UserNumExpert, UserNumEngineer = jobOld.UserNumEngineer, Title = jobOld.Title, Description = note, TimeEstimate = TimeSpan.FromHours(jobNew.HoursEstimate) }; JobLogs.Insert(jobLog); JobNotifications.UpsertAllNotifications(jobNew, Security.CurUser.UserNum, JobNotificationChanges.CategoryChange); return(JobLogs.GetOne(jobLog.JobLogNum)); //to get new timestamp. }
///<summary>Makes a joblog entry for the passed in job, queries the database for the joblog that was just created and then returns it. ///Does not make a joblog for Complete or Cancelled jobs. Instead, simply returns null indicating that nothing happened.</summary> public static JobLog MakeLogEntryForView(Job job) { if (job.PhaseCur.In(JobPhase.Complete, JobPhase.Cancelled)) { return(null); } JobLog jobLog = new JobLog() { JobNum = job.JobNum, UserNumChanged = Security.CurUser.UserNum, UserNumExpert = job.UserNumExpert, UserNumEngineer = job.UserNumEngineer, Title = job.Title, Description = "Job Viewed", TimeEstimate = TimeSpan.FromHours(job.HoursEstimate) }; JobLogs.Insert(jobLog); return(JobLogs.GetOne(jobLog.JobLogNum)); //to get new timestamp. }
///<summary>Returns the jobs new list of JobActiveLinks</summary> public static List <JobActiveLink> UpsertLink(Job job, Job jobOld, long userNum, bool isActive) { //No need for remoting call here. List <JobActiveLink> listJobActiveLinks = job.ListJobActiveLinks; if (!jobOld.PhaseCur.In(JobPhase.Cancelled, JobPhase.Complete, JobPhase.Documentation) && job.PhaseCur.In(JobPhase.Cancelled, JobPhase.Complete, JobPhase.Documentation)) { EndForJobNum(job.JobNum); return(new List <JobActiveLink>()); } JobActiveLink activeLink = listJobActiveLinks.FirstOrDefault(x => x.JobNum == job.JobNum && x.UserNum == userNum && x.DateTimeEnd == DateTime.MinValue); if (activeLink == null) { if (!isActive) { return(listJobActiveLinks); } activeLink = new JobActiveLink(); activeLink.JobNum = job.JobNum; activeLink.UserNum = userNum; Insert(activeLink); } else { if (isActive) { return(listJobActiveLinks); } activeLink.DateTimeEnd = DateTime.Now; Update(activeLink); } //Only occurs if an actual db change happened for a single user //Mass delete does not make a log entry JobLogs.MakeLogEntryForActive(job, userNum, isActive); listJobActiveLinks.Add(activeLink); return(listJobActiveLinks); }
public static JobLog MakeLogEntryForRequirementApproval(Job job) { List <JobRequirement> listRequirements = JsonConvert.DeserializeObject <List <JobRequirement> >(job.RequirementsJSON); string logText = "Requirements Approved\r\n"; foreach (JobRequirement jobReq in listRequirements) { logText += "Requirement: " + jobReq.Description + "\r\n"; } JobLog jobLog = new JobLog() { JobNum = job.JobNum, UserNumChanged = Security.CurUser.UserNum, UserNumExpert = job.UserNumExpert, UserNumEngineer = job.UserNumEngineer, Title = job.Title, Description = logText, TimeEstimate = TimeSpan.FromHours(job.HoursEstimate) }; JobLogs.Insert(jobLog); return(JobLogs.GetOne(jobLog.JobLogNum)); //to get new timestamp. }
///<summary>Removes invalid jobs from the list of jobs passed in and then queries the DB to fill corresponding in-memory lists for remaining jobs. ///Set isForSearch true in order to only fill in-memory lists that are required for the Job Search window.</summary> public static void FillInMemoryLists(List <Job> listJobsAll, bool isForSearch = false) { //No need for remoting call here. listJobsAll.RemoveAll(x => x == null || x.JobNum == 0); List <long> jobNums = listJobsAll.Select(x => x.JobNum).ToList(); Dictionary <long, List <JobLink> > dictJobLinksAll = new Dictionary <long, List <JobLink> >(); Dictionary <long, List <JobNote> > dictJobNotesAll = new Dictionary <long, List <JobNote> >(); Dictionary <long, List <JobReview> > dictJobReviewsAll = new Dictionary <long, List <JobReview> >(); Dictionary <long, List <JobReview> > dictJobTimeLogsAll = new Dictionary <long, List <JobReview> >(); Dictionary <long, List <JobQuote> > dictJobQuotesAll = new Dictionary <long, List <JobQuote> >(); Dictionary <long, List <JobLog> > dictJobLogsAll = new Dictionary <long, List <JobLog> >(); Dictionary <long, List <JobNotification> > dictJobNotificationsAll = new Dictionary <long, List <JobNotification> >(); Dictionary <long, List <JobActiveLink> > dictJobActiveLinksAll = new Dictionary <long, List <JobActiveLink> >(); //The job search only needs ListJobLinks and ListJobReviews to be filled. dictJobLinksAll = JobLinks.GetJobLinksForJobs(jobNums).GroupBy(x => x.JobNum).ToDictionary(x => x.Key, x => x.ToList()); dictJobReviewsAll = JobReviews.GetReviewsForJobs(jobNums.ToArray()).GroupBy(x => x.JobNum).ToDictionary(x => x.Key, x => x.ToList()); //Fill all other dictionaries when not filling in-memory lists for job search results (saves db calls and memory usage). if (!isForSearch) { dictJobNotesAll = JobNotes.GetJobNotesForJobs(jobNums).GroupBy(x => x.JobNum).ToDictionary(x => x.Key, x => x.ToList()); dictJobTimeLogsAll = JobReviews.GetTimeLogsForJobs(jobNums.ToArray()).GroupBy(x => x.JobNum).ToDictionary(x => x.Key, x => x.ToList()); dictJobQuotesAll = JobQuotes.GetJobQuotesForJobs(jobNums).GroupBy(x => x.JobNum).ToDictionary(x => x.Key, x => x.ToList()); dictJobLogsAll = JobLogs.GetJobLogsForJobs(jobNums).GroupBy(x => x.JobNum).ToDictionary(x => x.Key, x => x.ToList()); dictJobNotificationsAll = JobNotifications.GetNotificationsForJobs(jobNums).GroupBy(x => x.JobNum).ToDictionary(x => x.Key, x => x.ToList()); dictJobActiveLinksAll = JobActiveLinks.GetJobActiveLinksForJobNums(jobNums).GroupBy(x => x.JobNum).ToDictionary(x => x.Key, x => x.ToList()); } foreach (Job job in listJobsAll) { if (!dictJobLinksAll.TryGetValue(job.JobNum, out job.ListJobLinks)) { job.ListJobLinks = new List <JobLink>(); //empty list if not found } if (!dictJobNotesAll.TryGetValue(job.JobNum, out job.ListJobNotes)) { job.ListJobNotes = new List <JobNote>(); //empty list if not found } if (!dictJobReviewsAll.TryGetValue(job.JobNum, out job.ListJobReviews)) { job.ListJobReviews = new List <JobReview>(); //empty list if not found } if (!dictJobTimeLogsAll.TryGetValue(job.JobNum, out job.ListJobTimeLogs)) { job.ListJobTimeLogs = new List <JobReview>(); //empty list if not found } if (!dictJobQuotesAll.TryGetValue(job.JobNum, out job.ListJobQuotes)) { job.ListJobQuotes = new List <JobQuote>(); //empty list if not found } if (!dictJobLogsAll.TryGetValue(job.JobNum, out job.ListJobLogs)) { job.ListJobLogs = new List <JobLog>(); //empty list if not found } if (!dictJobNotificationsAll.TryGetValue(job.JobNum, out job.ListJobNotifications)) { job.ListJobNotifications = new List <JobNotification>(); //empty list if not found } if (!dictJobActiveLinksAll.TryGetValue(job.JobNum, out job.ListJobActiveLinks)) { job.ListJobActiveLinks = new List <JobActiveLink>(); //empty list if not found } } }
/// <summary>Inserts log entry to DB and returns the resulting JobLog.</summary> public static JobLog MakeLogEntry(Job jobNew, Job jobOld, bool isManualLog = false) { if (jobNew == null) { return(null); //should never happen } JobLog jobLog = new JobLog() { JobNum = jobNew.JobNum, UserNumChanged = Security.CurUser.UserNum, UserNumExpert = jobNew.UserNumExpert, UserNumEngineer = jobNew.UserNumEngineer, Description = "" }; if (isManualLog) { jobLog.Description = "Manual \"last worked on\" update"; JobLogs.Insert(jobLog); return(JobLogs.GetOne(jobLog.JobLogNum)); //to get new timestamp. } List <string> logDescriptions = new List <string>(); if (jobOld.IsApprovalNeeded && !jobNew.IsApprovalNeeded) { if (jobOld.PhaseCur == JobPhase.Concept && (jobNew.PhaseCur == JobPhase.Definition || jobNew.PhaseCur == JobPhase.Development)) { logDescriptions.Add("Concept approved."); jobLog.MainRTF = jobNew.Implementation; jobLog.RequirementsRTF += jobNew.Requirements; } if ((jobOld.PhaseCur == JobPhase.Concept || jobOld.PhaseCur == JobPhase.Definition) && jobNew.PhaseCur == JobPhase.Development) { logDescriptions.Add("Job approved."); jobLog.MainRTF = jobNew.Implementation; jobLog.RequirementsRTF += jobNew.Requirements; } if (jobOld.PhaseCur == JobPhase.Development && jobNew.PhaseCur == JobPhase.Development) { logDescriptions.Add("Changes approved."); jobLog.MainRTF = jobNew.Implementation; jobLog.RequirementsRTF += jobNew.Requirements; } } else if (jobNew.PhaseCur.In(JobPhase.Documentation, JobPhase.Complete) && !jobOld.PhaseCur.In(JobPhase.Documentation, JobPhase.Complete)) { logDescriptions.Add("Job implemented."); jobLog.MainRTF += jobNew.Implementation; jobLog.RequirementsRTF += jobNew.Requirements; } if (jobOld.PhaseCur > jobNew.PhaseCur && jobOld.PhaseCur != JobPhase.Cancelled) { logDescriptions.Add("Job Unapproved."); //may be a chance for a false positive when using override permission. } if (jobOld.PhaseCur != JobPhase.Cancelled && jobNew.PhaseCur == JobPhase.Cancelled) { logDescriptions.Add("Job Cancelled."); //may be a chance for a false positive when using override permission. } if (jobNew.UserNumExpert != jobOld.UserNumExpert) { logDescriptions.Add("Expert changed."); } if (jobNew.UserNumEngineer != jobOld.UserNumEngineer) { logDescriptions.Add("Engineer changed."); } if (jobOld.Requirements != jobNew.Requirements) { logDescriptions.Add("Job Requirements Changed."); jobLog.RequirementsRTF += jobNew.Requirements; } if (jobOld.Implementation != jobNew.Implementation) { logDescriptions.Add("Job Implementation Changed."); jobLog.MainRTF += jobNew.Implementation; } if (jobOld.Title != jobNew.Title) { logDescriptions.Add("Job Title Changed."); } jobLog.Title = jobNew.Title; jobLog.Description = string.Join("\r\n", logDescriptions); JobLogs.Insert(jobLog); return(JobLogs.GetOne(jobLog.JobLogNum)); //to get new timestamp. }
/// <summary>Inserts log entry to DB and returns the resulting JobLog. Returns null if no log was needed.</summary> public static JobLog MakeLogEntry(Job jobNew, Job jobOld, bool isManualLog = false) { if (jobNew == null) { return(null); } JobNotificationChanges changes = new JobNotificationChanges(); JobLog jobLog = new JobLog() { JobNum = jobNew.JobNum, UserNumChanged = Security.CurUser.UserNum, UserNumExpert = jobNew.UserNumExpert, UserNumEngineer = jobNew.UserNumEngineer, Description = "", TimeEstimate = TimeSpan.FromHours(jobNew.HoursEstimate) }; if (isManualLog) { jobLog.Description = "Manual \"last worked on\" update"; JobLogs.Insert(jobLog); return(JobLogs.GetOne(jobLog.JobLogNum)); //to get new timestamp. } List <string> logDescriptions = new List <string>(); if (jobOld.IsApprovalNeeded && !jobNew.IsApprovalNeeded) { if (jobOld.PhaseCur == JobPhase.Concept && (jobNew.PhaseCur == JobPhase.Definition || jobNew.PhaseCur == JobPhase.Development)) { logDescriptions.Add("Concept approved."); jobLog.MainRTF = jobNew.Implementation; jobLog.RequirementsRTF += jobNew.Requirements; changes = changes | JobNotificationChanges.ApprovalChange; } if ((jobOld.PhaseCur == JobPhase.Concept || jobOld.PhaseCur == JobPhase.Definition) && jobNew.PhaseCur == JobPhase.Development) { logDescriptions.Add("Job approved."); jobLog.MainRTF = jobNew.Implementation; jobLog.RequirementsRTF += jobNew.Requirements; changes = changes | JobNotificationChanges.ApprovalChange; } if (jobOld.PhaseCur == JobPhase.Development && jobNew.PhaseCur == JobPhase.Development) { logDescriptions.Add("Changes approved."); jobLog.MainRTF = jobNew.Implementation; jobLog.RequirementsRTF += jobNew.Requirements; changes = changes | JobNotificationChanges.ApprovalChange; } } else if (jobNew.PhaseCur.In(JobPhase.Documentation, JobPhase.Complete) && !jobOld.PhaseCur.In(JobPhase.Documentation, JobPhase.Complete)) { logDescriptions.Add("Job implemented."); jobLog.MainRTF += jobNew.Implementation; jobLog.RequirementsRTF += jobNew.Requirements; } if (jobOld.PhaseCur > jobNew.PhaseCur && jobOld.PhaseCur != JobPhase.Cancelled) { logDescriptions.Add("Job Unapproved."); //may be a chance for a false positive when using override permission. } if (jobOld.PhaseCur != JobPhase.Cancelled && jobNew.PhaseCur == JobPhase.Cancelled) { logDescriptions.Add("Job Cancelled."); //may be a chance for a false positive when using override permission. } if (jobNew.UserNumExpert != jobOld.UserNumExpert) { logDescriptions.Add("Expert changed."); changes = changes | JobNotificationChanges.ExpertChange; } if (jobNew.UserNumEngineer != jobOld.UserNumEngineer) { logDescriptions.Add("Engineer changed."); changes = changes | JobNotificationChanges.EngineerChange; } if (jobOld.Requirements != jobNew.Requirements) { logDescriptions.Add("Job Requirements Changed."); jobLog.RequirementsRTF += jobNew.Requirements; changes = changes | JobNotificationChanges.ConceptChange; } if (jobOld.Implementation != jobNew.Implementation) { logDescriptions.Add("Job Implementation Changed."); jobLog.MainRTF += jobNew.Implementation; changes = changes | JobNotificationChanges.WriteupChange; } //Do not log RequirementsJSON changes here. //if(jobOld.RequirementsJSON!=jobNew.RequirementsJSON) { // logDescriptions.Add("Job Requirements List Changed."); // changes=changes|JobNotificationChanges.ConceptChange; //} if (jobOld.Title != jobNew.Title) { logDescriptions.Add("Job Title Changed."); } if (jobOld.HoursEstimate != jobNew.HoursEstimate) { logDescriptions.Add("Job Estimate Changed from " + jobOld.HoursEstimate.ToString() + " hour(s) to " + jobNew.HoursEstimate.ToString() + " hour(s)."); } jobLog.Title = jobNew.Title; jobLog.Description = string.Join("\r\n", logDescriptions); if (string.IsNullOrEmpty(jobLog.Description)) { return(null); } JobLogs.Insert(jobLog); JobNotifications.UpsertAllNotifications(jobNew, Security.CurUser.UserNum, changes); return(JobLogs.GetOne(jobLog.JobLogNum)); //to get new timestamp. }