using MesaFabApproval.Client.Pages.Components; using MesaFabApproval.Client.Services; using MesaFabApproval.Shared.Models; using MesaFabApproval.Shared.Utilities; using Microsoft.AspNetCore.Components; using Microsoft.Extensions.Caching.Memory; using MudBlazor; using System.Text; namespace MesaFabApproval.Client.Pages; public partial class PCRBSingle { [Inject] ISnackbar snackbar { get; set; } [Inject] IPCRBService pcrbService { get; set; } [Inject] IUserService userService { get; set; } [Inject] IMemoryCache cache { get; set; } [Inject] IConfiguration config { get; set; } [Inject] IDialogService dialogService { get; set; } [Inject] IApprovalService approvalService { get; set; } [Inject] NavigationManager navigationManager { get; set; } [Inject] MesaFabApprovalAuthStateProvider authStateProvider { get; set; } [Parameter] public string planNumber { get; set; } = ""; private int planNumberInt = 0; private PCRB pcrb = null; private IEnumerable approvals = new List(); private IEnumerable attendees = new List(); private IEnumerable attachments = new List(); private IEnumerable actionItems = new List(); private IEnumerable pcr3Documents = new List(); private IEnumerable qualityApproverUserIds = new List(); private IEnumerable allActiveUsers = new List(); private User selectedOwner = null; private bool processing = false; private bool saveInProcess = false; private bool deleteInProcess = false; private bool submitInProcess = false; private bool approvalInProcess = false; private bool denialInProcess = false; private bool recallInProcess = false; private bool attachmentUploadInProcess = false; private bool updateAttachmentInProcess = false; private bool deleteAttachmentInProcess = false; private bool addActionItemInProcess = false; private string attachmentSearchString = ""; private string actionItemSearchString = ""; protected override async Task OnParametersSetAsync() { processing = true; try { allActiveUsers = await userService.GetAllActiveUsers(); if (qualityApproverUserIds.Count() == 0) qualityApproverUserIds = await GetQualityApproverUserIds(); if (!string.IsNullOrWhiteSpace(planNumber) && Int32.TryParse(planNumber, out planNumberInt)) { pcrb = await pcrbService.GetPCRBByPlanNumber(planNumberInt, false); approvals = await approvalService.GetApprovalsForIssueId(planNumberInt, false); attendees = await pcrbService.GetAttendeesByPlanNumber(planNumberInt, true); attachments = await pcrbService.GetAttachmentsByPlanNumber(planNumberInt, false); actionItems = await pcrbService.GetActionItemsForPlanNumber(planNumberInt, false); pcr3Documents = await pcrbService.GetPCR3DocumentsForPlanNumber(planNumberInt, false); List createPCR3DocumentTasks = new(); if (pcr3Documents.Count() <= 0) { List docTypes = new() { "FMEA", "SOPs", "Work Instructions", "Forms/OCAPs", "OpenInsight", "SPC Charts", "Spare Parts Addition", "Metrology", "Safety (system/documents)", "Other" }; foreach (string docType in docTypes) { PCR3Document document = new() { PlanNumber = planNumberInt, DocType = docType }; createPCR3DocumentTasks.Add(pcrbService.CreatePCR3Document(document)); } } List generateAttendeesTasks = new(); if (attendees.Count() == 0) { for (int stepNo = 1; stepNo < 4; stepNo++) { generateAttendeesTasks.Add(GenerateAttendeesForStep(stepNo)); } } List generateApprovalsTasks = new(); if (approvals.Count() == 0) { for (int stepNo = 1; stepNo < 4; stepNo++) { generateApprovalsTasks.Add(GenerateApprovalsForStep(stepNo)); } } await Task.WhenAll(createPCR3DocumentTasks); pcr3Documents = await pcrbService.GetPCR3DocumentsForPlanNumber(planNumberInt, true); await Task.WhenAll(generateAttendeesTasks); attendees = await pcrbService.GetAttendeesByPlanNumber(planNumberInt, true); await Task.WhenAll(generateApprovalsTasks); approvals = await approvalService.GetApprovalsForIssueId(planNumberInt, true); if (pcrb.OwnerID > 0) selectedOwner = await userService.GetUserByUserId(pcrb.OwnerID); if (pcrb.CurrentStep > 0 && pcrb.CurrentStep < 4) { bool stageHasAdvanced = false; for (int stage = pcrb.CurrentStep; stage < 4; stage++) { int current_stage = stage; if (pcrb.CurrentStep == current_stage) { IEnumerable currentStageApprovals = approvals.Where(a => a.Step == current_stage); int currentStagePendingApprovalsCount = currentStageApprovals.Where(a => a.ItemStatus == 0).Count(); int currentStageApprovedApprovalsCount = currentStageApprovals.Where(a => a.ItemStatus == 1).Count(); bool currentStageApproved = currentStageApprovedApprovalsCount >= 3 && currentStagePendingApprovalsCount == 0; if (currentStageApproved) { if (pcrb.CurrentStep == 3) { int openActionItemCount = actionItems.Where(a => a.ClosedByID == 0).Count(); int openAffectedDocumentsCount = pcr3Documents.Where(d => d.CompletedByID == 0).Count(); if (openActionItemCount == 0 && openAffectedDocumentsCount == 0) { pcrb.CurrentStep++; stageHasAdvanced = true; } } else { pcrb.CurrentStep++; stageHasAdvanced = true; } } } } if (stageHasAdvanced) { if (pcrb.CurrentStep == 4) { pcrb.ClosedDate = DateTime.Now; string message = $"PCRB# {pcrb.PlanNumber} - {pcrb.Title} is complete"; PCRBNotification notification = new() { PCRB = pcrb, Message = message }; await pcrbService.NotifyOriginator(notification); } await pcrbService.UpdatePCRB(pcrb); pcrb = await pcrbService.GetPCRBByPlanNumber(pcrb.PlanNumber, true); StateHasChanged(); await OnParametersSetAsync(); } } } else { int ownerID = 0; string ownerName = string.Empty; if (authStateProvider.CurrentUser is not null) { selectedOwner = authStateProvider.CurrentUser; ownerID = authStateProvider.CurrentUser.UserID; ownerName = authStateProvider.CurrentUser.GetFullName(); } pcrb = new() { OwnerID = ownerID, OwnerName = ownerName, CurrentStep = 0 }; } processing = false; } catch (Exception ex) { processing = false; snackbar.Add(ex.Message, Severity.Error); } } private Func UserToNameConverter = u => u is null ? string.Empty : u.GetFullName(); private void ReturnToAllPcrbs() { cache.Set("redirectUrl", $"pcrb/all"); navigationManager.NavigateTo("pcrb/all"); } private IEnumerable GetIncompleteFields() { List incompleteFields = new(); if (string.IsNullOrWhiteSpace(pcrb.Title)) incompleteFields.Add("Title"); if (selectedOwner is null || pcrb.OwnerID <= 0 || string.IsNullOrWhiteSpace(pcrb.OwnerName)) incompleteFields.Add("Originator"); if (string.IsNullOrWhiteSpace(pcrb.ChangeLevel)) incompleteFields.Add("Change Level"); if (string.IsNullOrWhiteSpace(pcrb.ChangeDescription)) incompleteFields.Add("Description of Change"); if (string.IsNullOrWhiteSpace(pcrb.ReasonForChange)) incompleteFields.Add("Reason For Change"); return incompleteFields; } private bool PCRBReadyToSubmit(int step) { bool readyToSubmit = GetIncompleteFields().Count() <= 0; readyToSubmit = readyToSubmit && pcrb.CurrentStep > 0; readyToSubmit = readyToSubmit && attachments.Where(a => a.Step == step).Count() > 0; return readyToSubmit; } private bool UserIsApprover() { bool userIsApprover = approvals.Where(a => authStateProvider.CurrentUser is not null && a.UserID == authStateProvider.CurrentUser.UserID && a.ItemStatus == 0).Count() > 0; return userIsApprover; } private async void SavePCRB() { if (!saveInProcess) { saveInProcess = true; try { if (pcrb is null) throw new Exception("PCRB cannot be null"); int initialPlanNumber = pcrb.PlanNumber; pcrb.OwnerID = selectedOwner.UserID; pcrb.OwnerName = selectedOwner.GetFullName(); if (pcrb.CurrentStep == 0 && GetIncompleteFields().Count() <= 0) pcrb.CurrentStep++; if (initialPlanNumber <= 0) { await pcrbService.CreateNewPCRB(pcrb); } else { await pcrbService.UpdatePCRB(pcrb); } pcrb = await pcrbService.GetPCRBByTitle(pcrb.Title, true); cache.Set("redirectUrl", $"pcrb/{pcrb.PlanNumber}"); saveInProcess = false; StateHasChanged(); snackbar.Add($"PCRB {pcrb.PlanNumber} successfully saved", Severity.Success); if (initialPlanNumber <= 0) navigationManager.NavigateTo($"pcrb/{pcrb.PlanNumber}"); } catch (Exception ex) { saveInProcess = false; snackbar.Add($"Unable to save PCRB, because {ex.Message}", Severity.Error); } } } private async Task DeletePCRB() { if (!deleteInProcess) { deleteInProcess = true; try { bool? result = await dialogService.ShowMessageBox( "Warning", $"Are you sure you want to delete PCRB# {pcrb.PlanNumber}?", yesText: "Yes", noText: "No" ); if (result == true) { if (pcrb is null) throw new Exception("PCRB cannot be null"); await pcrbService.DeletePCRB(pcrb.PlanNumber); await pcrbService.GetAllPCRBs(true); deleteInProcess = false; snackbar.Add("PCRB successfully deleted", Severity.Success); cache.Set("redirectUrl", "pcrb/all"); navigationManager.NavigateTo($"pcrb/all"); } } catch (Exception ex) { deleteInProcess = false; snackbar.Add(ex.Message, Severity.Error); } } } private async Task> GetQualityApproverUserIds() { List qualityApproverUserIds = new(); try { int roleId = await approvalService.GetRoleIdForRoleName("Module Manager"); if (roleId <= 0) throw new Exception($"could not find Module Manager role ID"); IEnumerable subRoles = await approvalService.GetSubRolesForSubRoleName("MMSubRole", roleId); foreach (SubRole subRole in subRoles) { if (subRole.SubRoleCategoryItem.Equals("Quality", StringComparison.InvariantCultureIgnoreCase)) { IEnumerable subRoleMembers = await approvalService.GetApprovalGroupMembers(subRole.SubRoleID); foreach (User user in subRoleMembers) qualityApproverUserIds.Add(user.UserID); } } string roleName = "QA_PRE_APPROVAL"; string subRoleName = "QA_PRE_APPROVAL"; roleId = await approvalService.GetRoleIdForRoleName(roleName); if (roleId <= 0) throw new Exception($"could not find {roleName} role ID"); subRoles = await approvalService.GetSubRolesForSubRoleName(subRoleName, roleId); foreach (SubRole subRole in subRoles) { IEnumerable subRoleMembers = await approvalService.GetApprovalGroupMembers(subRole.SubRoleID); foreach (User user in subRoleMembers) qualityApproverUserIds.Add(user.UserID); } return qualityApproverUserIds; } catch (Exception ex) { snackbar.Add($"Unable to get Quality approvers, because {ex.Message}", Severity.Error); return qualityApproverUserIds; } } private async Task GenerateApprovalsForStep(int step) { try { if (pcrb is null) throw new Exception("PCRB cannot be null"); int roleId = await approvalService.GetRoleIdForRoleName("QA_PRE_APPROVAL"); if (roleId <= 0) throw new Exception($"could not find QA_PRE_APPROVAL role ID"); IEnumerable subRoles = await approvalService.GetSubRolesForSubRoleName("QA_PRE_APPROVAL", roleId); foreach (SubRole subRole in subRoles) { IEnumerable members = await approvalService.GetApprovalGroupMembers(subRole.SubRoleID); foreach (User member in members) { Approval approval = new() { IssueID = pcrb.PlanNumber, RoleName = subRole.SubRoleCategoryItem, SubRole = subRole.SubRoleName, UserID = member.UserID, SubRoleID = subRole.SubRoleID, AssignedDate = DateTimeUtilities.MIN_DT, Step = step }; await approvalService.CreateApproval(approval); } } roleId = await approvalService.GetRoleIdForRoleName("Module Manager"); if (roleId <= 0) throw new Exception($"could not find Module Manager role ID"); subRoles = await approvalService.GetSubRolesForSubRoleName("MMSubRole", roleId); HashSet subRoleCategoryItems = new() { "Si Production", "Si Engineering", "Quality" }; foreach (SubRole subRole in subRoles) { if (subRoleCategoryItems.Contains(subRole.SubRoleCategoryItem)) { IEnumerable subRoleMembers = await approvalService.GetApprovalGroupMembers(subRole.SubRoleID); foreach (User member in subRoleMembers) { Approval approval = new() { IssueID = pcrb.PlanNumber, RoleName = subRole.SubRoleCategoryItem, SubRole = subRole.SubRoleName, UserID = member.UserID, SubRoleID = subRole.SubRoleID, AssignedDate = DateTimeUtilities.MIN_DT, Step = step }; await approvalService.CreateApproval(approval); } } } } catch (Exception ex) { snackbar.Add($"Unable to generate approvals for step {step}, because {ex.Message}", Severity.Error); } } private async Task SubmitForApproval(int step) { if (!submitInProcess) { try { submitInProcess = true; if (pcrb is null) throw new Exception("PCRB cannot be null"); if (!PCRBReadyToSubmit(step)) throw new Exception($"PCR {step} not ready to submit"); List attendeeTasks = new(); foreach (PCRBAttendee attendee in attendees.Where(a => a.Step == step)) { attendeeTasks.Add(pcrbService.UpdateAttendee(attendee)); } await Task.WhenAll(attendeeTasks); List notifyResponsiblePersonsTasks = new(); foreach (PCRBActionItem actionItem in actionItems.Where(a => a.Step == step && a.NotifyDate <= DateTimeUtilities.MIN_DT && a.ClosedStatus == false)) { StringBuilder messageBuilder = new(); messageBuilder.Append($"PCRB# {pcrb.PlanNumber} [{pcrb.Title}] PCR{step} has an action item for you to complete. "); messageBuilder.Append($"The action is {actionItem.Name}."); PCRBActionItemNotification notification = new() { PCRB = pcrb, ActionItem = actionItem, Message = messageBuilder.ToString() }; actionItem.NotifyDate = DateTime.Now; notifyResponsiblePersonsTasks.Add(pcrbService.NotifyResponsiblePerson(notification)); notifyResponsiblePersonsTasks.Add(pcrbService.UpdateActionItem(actionItem)); } await Task.WhenAll(notifyResponsiblePersonsTasks); IEnumerable currentStageApprovals = approvals.Where(a => a.Step == step); IEnumerable currentStageManagerApprovals = currentStageApprovals.Where(a => !a.SubRoleCategoryItem.Equals("QA Pre Approver")); int currentStageUnsubmittedApprovalCount = currentStageManagerApprovals.Where(a => a.AssignedDate <= DateTimeUtilities.MIN_DT).Count(); int currentStagePendingApprovalsCount = currentStageManagerApprovals.Where(a => a.ItemStatus == 0 && a.AssignedDate > DateTimeUtilities.MIN_DT).Count(); int currentStageApprovedApprovalsCount = currentStageManagerApprovals.Where(a => a.ItemStatus == 1).Count(); int currentStageDeniedApprovalsCount = currentStageManagerApprovals.Where(a => a.ItemStatus == -1).Count(); Approval? latestQaPreApproval = currentStageApprovals .Where(a => a.SubRoleCategoryItem.Equals("QA Pre Approver")) .OrderByDescending(a => a.AssignedDate) .FirstOrDefault(); if (latestQaPreApproval is null) throw new Exception("QA pre approval not found"); bool qaPreApprovalDenied = latestQaPreApproval.ItemStatus == -1; if (qaPreApprovalDenied && currentStageUnsubmittedApprovalCount >= 3) { Approval newApproval = new() { IssueID = latestQaPreApproval.IssueID, RoleName = latestQaPreApproval.RoleName, SubRole = latestQaPreApproval.SubRole, UserID = latestQaPreApproval.UserID, SubRoleID = latestQaPreApproval.SubRoleID, AssignedDate = DateTime.Now, Step = latestQaPreApproval.Step }; await approvalService.CreateApproval(newApproval); } else if (currentStageDeniedApprovalsCount > (currentStageUnsubmittedApprovalCount + currentStagePendingApprovalsCount + currentStageApprovedApprovalsCount)) { HashSet copiedApprovals = new(); List createCopiedApprovalsTasks = new(); foreach (Approval oldApproval in currentStageApprovals) { if (!copiedApprovals.Contains($"{oldApproval.RoleName}{oldApproval.UserID}")) { DateTime assignedDate = DateTimeUtilities.MIN_DT; if (oldApproval.RoleName.Equals("QA Pre Approver")) assignedDate = DateTime.Now; Approval newApproval = new() { IssueID = oldApproval.IssueID, RoleName = oldApproval.RoleName, SubRole = oldApproval.SubRole, UserID = oldApproval.UserID, SubRoleID = oldApproval.SubRoleID, AssignedDate = assignedDate, Step = oldApproval.Step }; createCopiedApprovalsTasks.Add(approvalService.CreateApproval(newApproval)); copiedApprovals.Add($"{oldApproval.RoleName}{oldApproval.UserID}"); } } await Task.WhenAll(createCopiedApprovalsTasks); } else { Approval? unassignedQaPreApproval = currentStageApprovals.Where(a => a.SubRoleCategoryItem.Equals("QA Pre Approver") && a.AssignedDate <= DateTimeUtilities.MIN_DT).FirstOrDefault(); if (unassignedQaPreApproval is null) throw new Exception("unassigned QA pre approval not found"); unassignedQaPreApproval.AssignedDate = DateTime.Now; await approvalService.UpdateApproval(unassignedQaPreApproval); } approvals = await approvalService.GetApprovalsForIssueId(pcrb.PlanNumber, true); await pcrbService.NotifyNewApprovals(pcrb); if (pcrb.CurrentStep == 1) { pcrb.InsertTimeStamp = DateTime.Now; await pcrbService.UpdatePCRB(pcrb); pcrb = await pcrbService.GetPCRBByPlanNumber(pcrb.PlanNumber, true); } submitInProcess = false; snackbar.Add("PCRB successfully submitted for approval", Severity.Success); } catch (Exception ex) { submitInProcess = false; snackbar.Add($"Unable to submit for approval, because {ex.Message}", Severity.Error); } StateHasChanged(); await OnParametersSetAsync(); } } private async Task SetUserForApproval(Approval approval, User user) { if (approval is null) throw new ArgumentNullException("approval cannot be null"); if (user is null) throw new ArgumentNullException("user cannot be null"); if (approval.CompletedDate < DateTimeUtilities.MAX_DT || approval.ItemStatus != 0) throw new ArgumentException("cannot reassign a complete approval"); approval.UserID = user.UserID; approval.User = user; approval.NotifyDate = DateTimeUtilities.MIN_DT; await approvalService.UpdateApproval(approval); await approvalService.GetApprovalsForIssueId(approval.IssueID, true); await pcrbService.NotifyNewApprovals(pcrb); } private async Task ApprovePCR(int step) { if (!processing) { try { processing = true; if (step <= 0 || step > 3) throw new Exception($"{step} is not a valid PCR#"); if (pcrb is null) throw new Exception("PCRB cannot be null"); if (pcrb.ClosedDate < DateTimeUtilities.MAX_DT) throw new Exception("cannot approve a complete PCRB"); if (authStateProvider.CurrentUser is null) { await authStateProvider.Logout(); navigationManager.NavigateTo("login"); return; } IEnumerable activeApprovalsForUser = approvals.Where(a => a.UserID == authStateProvider.CurrentUser.UserID && a.AssignedDate > DateTimeUtilities.MIN_DT && a.ItemStatus == 0 && a.Step == step); if (activeApprovalsForUser.Count() <= 0) throw new Exception($"you have no active approvals for PCR{step}"); string? comments = ""; DialogParameters parameters = new DialogParameters { { x => x.comments, comments } }; var dialog = dialogService.Show($"Approval Comments", parameters); var result = await dialog.Result; if (result.Canceled) throw new Exception("you must provide approval comments"); comments = result.Data.ToString(); foreach (Approval approval in activeApprovalsForUser) { approval.CompletedDate = DateTime.Now; approval.Comments = comments is null ? "" : comments; approval.ItemStatus = 1; await approvalService.UpdateApproval(approval); } approvals = await approvalService.GetApprovalsForIssueId(pcrb.PlanNumber, false); IEnumerable unassignedApprovals = approvals.Where(a => a.Step == step && a.AssignedDate <= DateTimeUtilities.MIN_DT); if (unassignedApprovals.Count() > 0) { List assignmentTasks = new(); foreach (Approval approval in unassignedApprovals) { approval.AssignedDate = DateTime.Now; assignmentTasks.Add(approvalService.UpdateApproval(approval)); } await Task.WhenAll(assignmentTasks); approvals = await approvalService.GetApprovalsForIssueId(pcrb.PlanNumber, false); await pcrbService.NotifyNewApprovals(pcrb); } IEnumerable remainingActiveApprovals = approvals.Where(a => a.Step == step && a.ItemStatus == 0); if (remainingActiveApprovals.Count() <= 0) { StringBuilder messageBuilder = new(); messageBuilder.Append($"PCRB# {pcrb.PlanNumber} - {pcrb.Title} - PCR{step} has been approved."); PCRBNotification notification = new() { PCRB = pcrb, Message = messageBuilder.ToString() }; await pcrbService.NotifyOriginator(notification); } processing = false; snackbar.Add($"PCR{step} successfully approved", Severity.Success); } catch (Exception ex) { processing = false; snackbar.Add($"Unable to approve PCR{step}, because {ex.Message}", Severity.Error); } StateHasChanged(); await OnParametersSetAsync(); } } private async Task DenyPCR(int step) { if (!processing) { try { processing = true; if (step <= 0 || step > 3) throw new Exception($"{step} is not a valid PCR#"); if (pcrb is null) throw new Exception("PCRB cannot be null"); if (pcrb.ClosedDate < DateTimeUtilities.MAX_DT) throw new Exception("cannot deny a complete PCRB"); if (authStateProvider.CurrentUser is null) { await authStateProvider.Logout(); navigationManager.NavigateTo("login"); return; } IEnumerable activeApprovalsForUser = approvals.Where(a => a.UserID == authStateProvider.CurrentUser.UserID && a.AssignedDate > DateTimeUtilities.MIN_DT && a.ItemStatus == 0 && a.Step == step); if (activeApprovalsForUser.Count() <= 0) throw new Exception("you have no active approvals"); string? comments = ""; DialogParameters parameters = new DialogParameters { { x => x.comments, comments } }; var dialog = dialogService.Show($"Denial Comments", parameters); var result = await dialog.Result; if (result.Canceled) throw new Exception("you must provide a comment"); comments = result.Data.ToString(); IEnumerable outstandingActiveApprovalsForStep = approvals.Where(a => a.Step == step && a.ItemStatus == 0 && a.AssignedDate > DateTimeUtilities.MIN_DT); foreach (Approval approval in outstandingActiveApprovalsForStep) { approval.CompletedDate = DateTime.Now; approval.Comments = comments is null ? "" : comments; approval.ItemStatus = -1; await approvalService.UpdateApproval(approval); } approvals = await approvalService.GetApprovalsForIssueId(pcrb.PlanNumber, false); if (step == 1) { pcrb.InsertTimeStamp = DateTimeUtilities.MIN_DT; await pcrbService.UpdatePCRB(pcrb); } StringBuilder messageBuilder = new(); messageBuilder.Append($"PCRB# {pcrb.PlanNumber} - {pcrb.Title} - PCR{step} has been denied "); messageBuilder.Append($"by {authStateProvider.CurrentUser.GetFullName()}. "); messageBuilder.AppendLine(""); messageBuilder.Append($"Comments: {comments}"); PCRBNotification notification = new() { PCRB = pcrb, Message = messageBuilder.ToString() }; await pcrbService.NotifyOriginator(notification); processing = false; snackbar.Add($"PCR{step} successfully denied", Severity.Success); } catch (Exception ex) { processing = false; snackbar.Add($"Unable to deny PCR{step}, because {ex.Message}", Severity.Error); } StateHasChanged(); await OnParametersSetAsync(); } } private async Task UploadAttachment(int step) { if (!attachmentUploadInProcess) { attachmentUploadInProcess = true; try { if (step <= 0) throw new ArgumentException($"{step} is not a valid PCRB stage#"); DialogParameters parameters = new DialogParameters { { x => x.planNumber, pcrb.PlanNumber }, { x => x.step, step } }; var dialog = dialogService.Show("Upload Attachment", parameters); var result = await dialog.Result; if (result is not null && !result.Canceled) snackbar.Add("Attachment successfully uploaded", Severity.Success); attachments = await pcrbService.GetAttachmentsByPlanNumber(planNumberInt, true); attachmentUploadInProcess = false; } catch (Exception ex) { attachmentUploadInProcess = false; snackbar.Add($"Unable to upload attachment, because {ex.Message}", Severity.Error); } StateHasChanged(); await OnParametersSetAsync(); } } private async Task DeleteAttachment(PCRBAttachment attachment) { try { processing = true; if (attachment is null) throw new ArgumentNullException("attachment cannot be null"); bool? result = await dialogService.ShowMessageBox( "Warning", $"Are you sure you want to delete PCRB attachment {attachment.FileName}?", yesText: "Yes", noText: "No" ); if (result == true) { await pcrbService.DeleteAttachment(attachment); attachments = await pcrbService.GetAttachmentsByPlanNumber(attachment.PlanNumber, true); } processing = false; snackbar.Add("Attachment successfully deleted", Severity.Success); } catch (Exception ex) { processing = false; snackbar.Add($"Unable to delete attachment, because {ex.Message}", Severity.Error); } StateHasChanged(); await OnParametersSetAsync(); } private async Task CreateNewActionItem(int step) { try { DialogParameters parameters = new DialogParameters { { x => x.planNumber, pcrb.PlanNumber }, { x => x.step, step }, { x => x.allActiveUsers, allActiveUsers } }; var dialog = dialogService.Show("New Action Item", parameters); var result = await dialog.Result; if (result is not null && !result.Canceled) snackbar.Add("Action item successfully created", Severity.Success); actionItems = await pcrbService.GetActionItemsForPlanNumber(pcrb.PlanNumber, true); } catch (Exception ex) { snackbar.Add($"Unable to create new action item, because {ex.Message}", Severity.Error); } StateHasChanged(); await OnParametersSetAsync(); } private async Task CloseAllActionItems(int step) { if (!processing) { try { processing = true; if (authStateProvider.CurrentUser is null) { await authStateProvider.Logout(); navigationManager.NavigateTo("login"); return; } IEnumerable outstandingActionItemsForStep = actionItems.Where(a => a.Step == step && a.ClosedStatus == false); foreach (PCRBActionItem actionItem in outstandingActionItemsForStep) { actionItem.ClosedStatus = true; actionItem.ClosedDate = DateTime.Now; actionItem.ClosedBy = authStateProvider.CurrentUser; actionItem.ClosedByID = authStateProvider.CurrentUser.UserID; await pcrbService.UpdateActionItem(actionItem); } actionItems = await pcrbService.GetActionItemsForPlanNumber(planNumberInt, true); processing = false; snackbar.Add("Successfully approved all action items", Severity.Success); } catch (Exception ex) { processing = false; snackbar.Add($"Unable to approve all action items, because {ex.Message}", Severity.Error); } StateHasChanged(); await OnParametersSetAsync(); } } private async Task UpdateActionItem(PCRBActionItem actionItem) { try { if (actionItem is null) throw new ArgumentNullException("action item cannot be null"); DialogParameters parameters = new DialogParameters { { x => x.planNumber, pcrb.PlanNumber }, { x => x.step, actionItem.Step }, { x => x.allActiveUsers, allActiveUsers }, { x => x.actionItem, actionItem } }; var dialog = dialogService.Show("Update Action Item", parameters); var result = await dialog.Result; if (result is not null && !result.Canceled) snackbar.Add("Action item successfully updated", Severity.Success); actionItems = await pcrbService.GetActionItemsForPlanNumber(actionItem.PlanNumber, true); } catch (Exception ex) { snackbar.Add($"Unable to update action item, because {ex.Message}", Severity.Error); } StateHasChanged(); await OnParametersSetAsync(); } private async Task DeleteActionItem(PCRBActionItem actionItem) { try { if (actionItem is null) throw new ArgumentNullException("action item cannot be null"); bool? result = await dialogService.ShowMessageBox( "Warning", $"Are you sure you want to delete PCRB action item {actionItem.Name}?", yesText: "Yes", noText: "No" ); if (result == true) { await pcrbService.DeleteActionItem(actionItem.ID); actionItems = await pcrbService.GetActionItemsForPlanNumber(pcrb.PlanNumber, true); snackbar.Add("Action item successfully deleted", Severity.Success); } } catch (Exception ex) { snackbar.Add($"Unable to delete action item, because {ex.Message}", Severity.Error); } StateHasChanged(); await OnParametersSetAsync(); } private async Task UpdatePCR3Document(PCR3Document document) { if (!processing) { try { processing = true; if (document is null) throw new Exception("affected document cannot be null"); DialogParameters parameters = new DialogParameters { { x => x.document, document }, }; var dialog = dialogService.Show("Update Affected Document Type", parameters); var result = await dialog.Result; processing = false; if (result is not null && !result.Canceled) snackbar.Add("Affected document successfully updated", Severity.Success); } catch (Exception ex) { processing = false; snackbar.Add($"Unable to update affected document, because {ex.Message}", Severity.Error); } StateHasChanged(); await OnParametersSetAsync(); } } private async Task GenerateAttendeesForStep(int step) { try { if (pcrb is null) throw new Exception("PCRB cannot be null"); int roleId = await approvalService.GetRoleIdForRoleName("PCRB Attendee"); if (roleId <= 0) throw new Exception($"could not find PCRB Attendee role ID"); IEnumerable subRoles = await approvalService.GetSubRolesForSubRoleName("PCRBAttendee", roleId); foreach (SubRole subRole in subRoles) { IEnumerable subRoleMembers = await approvalService.GetApprovalGroupMembers(subRole.SubRoleID); foreach (User member in subRoleMembers) { PCRBAttendee attendee = new() { PlanNumber = pcrb.PlanNumber, AttendeeID = member.UserID, Attendee = member, Step = step }; await pcrbService.CreateNewAttendee(attendee); } } } catch (Exception ex) { snackbar.Add($"Unable to generate attendees for step {step}, because {ex.Message}", Severity.Error); } } private async Task UpdateAttendees(IEnumerable pcrAttendees, int step) { if (!processing) { try { processing = true; List attendeeTasks = new(); foreach (PCRBAttendee attendee in pcrAttendees) { attendeeTasks.Add(pcrbService.UpdateAttendee(attendee)); } await Task.WhenAll(attendeeTasks); processing = false; snackbar.Add($"PCR{step} attendees updated", Severity.Success); } catch (Exception ex) { processing = false; snackbar.Add($"", Severity.Error); } } } private async Task AddAttendee(int step) { if (!processing) { try { processing = true; if (authStateProvider.CurrentUser is null) { await authStateProvider.Logout(); navigationManager.NavigateTo("login"); return; } if (pcrb is null) throw new Exception("PCRB cannot be null"); if (pcrb.PlanNumber == 0) throw new Exception("PCRB was never saved"); User user = authStateProvider.CurrentUser; DialogParameters parameters = new DialogParameters { { x => x.selectedUser, user } }; var dialog = dialogService.Show("Add Attendee", parameters); var result = await dialog.Result; if (result is not null && !result.Canceled && result.Data is not null) { user = (User)result.Data; if (attendees.Where(a => a.AttendeeID == user.UserID).Count() == 0) { PCRBAttendee attendee = new() { PlanNumber = pcrb.PlanNumber, Attendee = user, AttendeeID = user.UserID, Step = step }; await pcrbService.CreateNewAttendee(attendee); } } attendees = await pcrbService.GetAttendeesByPlanNumber(pcrb.PlanNumber, true); processing = false; } catch (Exception ex) { processing = false; snackbar.Add($"Unable to add attendee, because {ex.Message}", Severity.Error); } StateHasChanged(); await OnParametersSetAsync(); } } private async Task MarkAttended(PCRBAttendee attendee) { if (!processing) { try { processing = true; attendee.Attended = !attendee.Attended; await pcrbService.UpdateAttendee(attendee); processing = false; } catch (Exception ex) { processing = false; snackbar.Add($"Unable to mark attendance, because {ex.Message}", Severity.Error); } StateHasChanged(); await OnParametersSetAsync(); } } private async Task MarkAllAttended(int step) { if (!processing) { try { processing = true; List updateAttendeeTasks = new(); foreach (PCRBAttendee attendee in attendees.Where(a => a.Step == step)) { attendee.Attended = true; updateAttendeeTasks.Add(pcrbService.UpdateAttendee(attendee)); } await Task.WhenAll(updateAttendeeTasks); processing = false; } catch (Exception ex) { processing = false; snackbar.Add($"Unable to mark all attended, because {ex.Message}", Severity.Error); } StateHasChanged(); await OnParametersSetAsync(); } } private async Task AddApprover(int step) { try { DialogParameters parameters = new DialogParameters { { x => x.planNumber, pcrb.PlanNumber }, { x => x.step, step } }; var dialog = dialogService.Show("Add Approver", parameters); var result = await dialog.Result; if (result is not null && !result.Canceled) snackbar.Add("Approver successfully added", Severity.Success); approvals = await approvalService.GetApprovalsForIssueId(pcrb.PlanNumber, false); } catch (Exception ex) { snackbar.Add($"Unable to add approver, because {ex.Message}", Severity.Error); } StateHasChanged(); await OnParametersSetAsync(); } private async Task UpdateApproval(Approval approval) { try { if (approval is null) throw new ArgumentNullException("approval cannot be null"); DialogParameters parameters = new DialogParameters { { x => x.planNumber, pcrb.PlanNumber }, { x => x.step, approval.Step }, { x => x.approval, approval } }; var dialog = dialogService.Show("Update Approval", parameters); var result = await dialog.Result; if (result is not null && !result.Canceled) snackbar.Add("Approval successfully updated", Severity.Success); approvals = await approvalService.GetApprovalsForIssueId(pcrb.PlanNumber, true); } catch (Exception ex) { snackbar.Add($"Unable to update approval, because {ex.Message}", Severity.Error); } StateHasChanged(); await OnParametersSetAsync(); } private string SubRoleCategoryItemToJobTitleConverter(string subRoleCategoryItem) { if (string.IsNullOrWhiteSpace(subRoleCategoryItem)) return ""; string jobTitle = subRoleCategoryItem.Replace("Si", ""); if (!jobTitle.Contains("other", StringComparison.InvariantCultureIgnoreCase) && !jobTitle.Contains("qa pre approver", StringComparison.InvariantCultureIgnoreCase)) jobTitle = jobTitle + " Manager"; return jobTitle; } private string GetApprovalStatus(int itemStatus) { if (itemStatus < 0) return "Denied"; if (itemStatus > 0) return "Approved"; return "Pending"; } }