public ActionResult Create() { CheckCookies(); Ticket model = new Ticket(); model.DueDate = DateTimeOffset.UtcNow.AddDays(10); model.HoursToComplete = 1; UserRolesHelper helper = new UserRolesHelper(); var id = User.Identity.GetUserId(); var roles = helper.ListUserRoles(id); var highest = helper.GetHighestRole(id); ViewBag.HighestUserRole = highest; // Do this in every GET action... var uModel = ProjectsHelper.LoadUserModel(); ViewBag.UserModel = uModel; // If user is Submitter only (or has no role), don't allow Skill, Due Date, or HoursToComplete to show ViewBag.BaseOptionsOnly = (roles == null || ((roles.Count == 1) && (roles[0] == R.Submitter))) ? true : false; // If Admin, allow to select Developer when creating the ticket if (uModel.IsAdmin || uModel.IsPM) { var roleDev = db.Roles.FirstOrDefault(r => r.Name == R.Developer); ViewBag.CanAssignDeveloper = true; if (roleDev != null) { ViewBag.AssignedToDevId = new SelectList(db.Users .Where(d => d.Roles.FirstOrDefault(r => r.RoleId == roleDev.Id) != null), "Id", "UserName"); } else ViewBag.AssignedToDevId = Enumerable.Empty<SelectListItem>(); } else { ViewBag.AssignedToDevId = Enumerable.Empty<SelectListItem>(); ViewBag.CanAssignDeveloper = false; } ViewBag.OwnerUserId = new SelectList(db.Users, "Id", "FirstName"); ViewBag.ProjectId = new SelectList(db.Projects, "Id", "Name"); ViewBag.SkillRequiredId = new SelectList(db.SkillLevels, "Id", "Name"); ViewBag.TicketPriorityId = new SelectList(db.TicketPriorities, "Id", "Name"); ViewBag.TicketStatusId = new SelectList(db.TicketStatuses, "Id", "Name"); ViewBag.TicketTypeId = new SelectList(db.TicketTypes, "Id", "Name"); return View(model); }
public static void Notify(ApplicationDbContext db, Ticket ticket, DateTimeOffset date, EType type) { // Create new object, init fields and save TicketNotification tn = new TicketNotification(); // Don't need to create notification if the Developer is same as the User who generated the event if (ticket.AssignedToDevId != null) { if (ticket.AssignedToDevId != ticket.OwnerUserId) { tn.TicketId = ticket.Id; tn.UserId = ticket.AssignedToDevId; tn.Type = type; tn.Created = DateTimeOffset.UtcNow; db.TicketNotifications.Add(tn); db.SaveChanges(); } } }
private void CreateHistoryElement(ApplicationDbContext db, DateTimeOffset date, Prop prop, Ticket origTicket, string oldVal, string newVal) { TicketHistory history = new TicketHistory(); history.TicketId = origTicket.Id; history.TypeProperty = prop; history.OldValue = oldVal; history.NewValue = newVal; history.UserId = new UserRolesHelper().GetCurrentUserId(); history.SetDate(date); db.TicketHistories.Add(history); }
private bool CheckProperties(ApplicationDbContext db, DateTimeOffset date, Prop prop, Ticket origTicket, string oldVal, string newVal) { if (oldVal != newVal){ CreateHistoryElement(db, date, prop, origTicket, oldVal, newVal); return true; } return false; }
public DateTimeOffset WasChanged(ApplicationDbContext db, Ticket origTicket) { // Compare each field of 'this' with 'origTicket'. If any field changed, // create History record and copy the new value to origTicket // Something could have changed, so this is the date to store in each record DateTimeOffset date = DateTimeOffset.UtcNow; bool changed = false; if (CheckProperties(db, date, Prop.ProjectId, origTicket, origTicket.ProjectId, this.ProjectId)) { changed = true; origTicket.ProjectId = this.ProjectId; } if (CheckProperties(db, date, Prop.TicketTypeId, origTicket, origTicket.TicketTypeId, this.TicketTypeId)) { changed = true; origTicket.TicketTypeId = this.TicketTypeId; } if (CheckProperties(db, date, Prop.TicketPriorityId, origTicket, origTicket.TicketPriorityId, this.TicketPriorityId)) { changed = true; origTicket.TicketPriorityId = this.TicketPriorityId; } if (CheckProperties(db, date, Prop.TicketStatusId, origTicket, origTicket.TicketStatusId, this.TicketStatusId)) { changed = true; origTicket.TicketStatusId = this.TicketStatusId; } if (CheckProperties(db, date, Prop.SkillRequiredId, origTicket, origTicket.SkillRequiredId, this.SkillRequiredId)) { changed = true; origTicket.SkillRequiredId = this.SkillRequiredId; } if (CheckProperties(db, date, Prop.Title, origTicket, origTicket.Title, this.Title)) { changed = true; origTicket.Title = this.Title; } if (CheckProperties(db, date, Prop.Description, origTicket, origTicket.Description, this.Description)) { changed = true; origTicket.Description = this.Description; } if (CheckProperties(db, date, Prop.DueDate, origTicket, origTicket.DueDate, this.DueDate)) { changed = true; origTicket.DueDate = this.DueDate; } if (CheckProperties(db, date, Prop.HoursToComplete, origTicket, origTicket.HoursToComplete, this.HoursToComplete)) { changed = true; origTicket.HoursToComplete = this.HoursToComplete; } if (CheckProperties(db, date, Prop.AssignedToDevId, origTicket, origTicket.AssignedToDevId, this.AssignedToDevId)) { changed = true; origTicket.AssignedToDevId = this.AssignedToDevId; } // Show whether any changes were made return changed ? date : DateTimeOffset.MinValue; }
private int AddNewTickets() { // Process each row, create new user int nTickets = 0; int row; string[] colData; string Creator, Dev, Name, Desc; row = Start - 1; UserRolesHelper helper = new UserRolesHelper(); var statuses = db.TicketStatuses.ToList(); var priorities = db.TicketPriorities.ToList(); var types = db.TicketTypes.ToList(); var skills = db.SkillLevels.ToList(); bool devOk = false; // Set to true if validated and ready to add to ticket // Use same time stamp for all tickets DateTimeOffset now = DateTimeOffset.UtcNow; // First, make sure all needed columns are present if (HeadingOffsets[(int)H.T_Title] < 0 || HeadingOffsets[(int)H.T_Description] < 0) { Section.LogErr(db, "Ticket on row " + (row + 1) + " is missing a column " + "(Title and Description are required) -- cannot process any Tickets"); return 0; } while (++row < (Count + Start)) { if (Source[row][0] != ';') { // Valid row to process, so get columns // // DON'T TRIM THE ROW!! If it's trimmed, the column positions will NOT line up with // what is expected, resulting in a crash! // colData = Source[row].Split('\t'); // These rules must be followed: // [] Title and Description must be non-empty // [] No uniqueness test -- OK to enter tickets with same Title/Description(??) // [] Developer must be in database // [] Developer must be in Developer role // [] TicketCreator must be in database // [] If ProjectTitle/Description cannot be found, leave as null // [] Parse DateCreated - default is Now // [] Parse DueDate - default is Now + 1 day // [] Parse HoursToComplete - default is 1 // [] Parse Type, Priority, Status, Skill - default is 1 // - load all values from db, find the match, if not found use default // // If rules not followed, show error and skip Ticket ticket = new Ticket(); ticket.Title = colData[HeadingOffsets[(int)H.T_Title]]; ticket.Description = colData[HeadingOffsets[(int)H.T_Description]]; Dev = colData[HeadingOffsets[(int)H.T_AssignedDeveloperUserName]]; Creator = colData[HeadingOffsets[(int)H.T_TicketCreatorUserName]]; ApplicationUser user = null; // Test column requirements now... if (ticket.Title.Length == 0 || ticket.Description.Length == 0) { Section.LogErr(db, "Ticket on row " + (row + 1) + " needs both a Title and a Description -- will be skipped"); continue; } // Validate Developer user = db.Users.FirstOrDefault(u => u.UserName == Dev); if (user == null) { if (Dev != "") Section.LogAlert(db, "DeveloperUser on row " + (row + 1) + " has UserName [" + Dev + "] not in database -- leaving field blank, will continue"); } else { // Dev is in database, now check role if (!helper.IsUserInRole(user.Id, R.Developer)) { Section.LogErr(db, "Ticket on row " + (row + 1) + " has AssignedDeveloper [" + user.UserName + "] not in 'Developer' role -- leaving field blank, will continue"); } else { devOk = true; // Flags us to create Notification if/when ticket added to table ticket.AssignedToDevId = user.Id; } } // Validate Creator user = db.Users.FirstOrDefault(u => u.UserName == Creator); if (user == null) { Section.LogAlert(db, "TicketCreator on row " + (row + 1) + " has UserName [" + Dev + "] not in database -- using name of current user for this Ticket"); ticket.OwnerUserId = helper.GetCurrentUserId(); } else { ticket.OwnerUserId = user.Id; } // Validate Project -- if not found, leave as null Name = colData[HeadingOffsets[(int)H.T_ProjectName]]; Desc = colData[HeadingOffsets[(int)H.T_ProjectDescription]]; var project = db.Projects.FirstOrDefault(p => p.Name == Name && p.Description == Desc); if (project != null) ticket.ProjectId = project.Id; else { if (Name != "" && Desc != "") Section.LogAlert(db, "Ticket on row " + (row + 1) + " has project not found in Projects table -- setting to null, will continue"); } // Check HoursToComplete int num; int.TryParse(colData[HeadingOffsets[(int)H.T_HoursToComplete]], out num); ticket.HoursToComplete = num < 1 ? 1 : num; // Parse Dates... DateTimeOffset date; DateTimeOffset.TryParse(colData[HeadingOffsets[(int)H.T_DateCreated]], out date); if (date == DateTimeOffset.MinValue) { ticket.Created = ticket.MostRecentUpdate = now; Section.LogAlert(db, "Ticket on row " + (row + 1) + " had invalid DateCreated -- using today's date"); } else ticket.Created = date; DateTimeOffset.TryParse(colData[HeadingOffsets[(int)H.T_DueDate]], out date); if (date == DateTimeOffset.MinValue) { ticket.DueDate = now.AddDays(10); Section.LogAlert(db, "Ticket on row " + (row + 1) + " had invalid DueDate -- set default date to 10 days from now"); } else ticket.DueDate = date; // Validate Type, Priority, Status, Skill -- set to 1 as default // Type string type = colData[HeadingOffsets[(int)H.T_TicketType]].ToUpper(); var tempType = types.Where(t => t.Name.ToUpper().Contains(type)); if (tempType.Count() == 1) ticket.TicketTypeId = tempType.ElementAt(0).Id; else { // Set to default, issue alert if invalid type specified ticket.TicketTypeId = 1; if (type != "") Section.LogAlert(db, "Ticket on row " + (row + 1) + " had invalid TicketType -- set to Bug"); } // Priority string priority = colData[HeadingOffsets[(int)H.T_TicketPriority]].ToUpper(); var tempPriority = priorities.Where(t => t.Name.ToUpper().Contains(priority)); if (tempPriority.Count() == 1) ticket.TicketPriorityId = tempPriority.ElementAt(0).Id; else { // Set to default, issue alert if invalid type specified ticket.TicketPriorityId = 3; if (type != "") Section.LogAlert(db, "Ticket on row " + (row + 1) + " had invalid TicketPriority -- set to Essential"); } // Status string status = colData[HeadingOffsets[(int)H.T_TicketStatus]].ToUpper(); var tempStatus = statuses.Where(t => t.Name.ToUpper().Contains(status)); if (tempStatus.Count() == 1) ticket.TicketStatusId = tempStatus.ElementAt(0).Id; else { // Set to default, issue alert if invalid type specified ticket.TicketStatusId = 1; if (type != "") Section.LogAlert(db, "Ticket on row " + (row + 1) + " had invalid TicketStatus -- set to New"); } // Skill string skill = colData[HeadingOffsets[(int)H.T_SkillRequired]].ToUpper(); var tempSkill = skills.Where(s => s.Name.ToUpper().Contains(skill)); if (tempSkill.Count() == 1) ticket.SkillRequiredId = tempSkill.ElementAt(0).Id; else { // Set to default, issue alert if invalid type specified ticket.SkillRequiredId = 1; if (type != "") Section.LogAlert(db, "Ticket on row " + (row + 1) + " had invalid SkillRequired -- set to Junior"); } // Last check... if ticket.StatusId is "New" and a developer is assigned, change to "AssignedToDev" if (ticket.AssignedToDev != null && ticket.TicketStatusId == (int)TS.Status.New) { Section.LogAlert(db, "Ticket on row " + (row + 1) + " has assigned developer -- set to AssignedToDev"); ticket.TicketStatusId = (int)TS.Status.AssignedToDev; } // We can add the Ticket now db.Tickets.Add(ticket); db.SaveChanges(); if (devOk) ticket.NotifyNewTicket(db); LogSuccess(db, "Added Ticket from row " + (row + 1)); nTickets++; } } return nTickets; }