diff --git a/MesaFabApproval.API/Services/PCRBService.cs b/MesaFabApproval.API/Services/PCRBService.cs index a71694d..6f23b07 100644 --- a/MesaFabApproval.API/Services/PCRBService.cs +++ b/MesaFabApproval.API/Services/PCRBService.cs @@ -485,6 +485,20 @@ public class PCRBService : IPCRBService { int rowsAffected = await _dalService.ExecuteAsync(queryBuilder.ToString()); if (rowsAffected <= 0) throw new Exception("update failed in database"); + + IEnumerable? attendees = _cache.Get>($"pcrbAttendees{attendee.PlanNumber}"); + if (attendees is not null) { + foreach (PCRBAttendee cachedAttendee in attendees) { + if (cachedAttendee.ID == attendee.ID) { + cachedAttendee.Location = attendee.Location; + cachedAttendee.Attended = attendee.Attended; + cachedAttendee.JobTitle = attendee.JobTitle; + cachedAttendee.AttendeeID = attendee.AttendeeID; + cachedAttendee.Step = attendee.Step; + } + } + _cache.Set($"pcrbAttendees{attendee.PlanNumber}", attendees, DateTimeOffset.Now.AddMinutes(15)); + } } catch (Exception ex) { _logger.LogError($"Unable to update attendee, because {ex.Message}"); throw; diff --git a/MesaFabApproval.Client/Pages/PCRBSingle.razor b/MesaFabApproval.Client/Pages/PCRBSingle.razor index 9299ad0..bc8fe34 100644 --- a/MesaFabApproval.Client/Pages/PCRBSingle.razor +++ b/MesaFabApproval.Client/Pages/PCRBSingle.razor @@ -2,16 +2,6 @@ @page "/pcrb/new" @using System.Text -@inject ISnackbar snackbar -@inject IPCRBService pcrbService -@inject IUserService userService -@inject IMemoryCache cache -@inject IConfiguration config -@inject IDialogService dialogService -@inject IApprovalService approvalService -@inject NavigationManager navigationManager -@inject MesaFabApprovalAuthStateProvider authStateProvider - PCRB @planNumber @@ -243,6 +233,9 @@ bool affectedDocumentsIncomplete = current_i == 3 && pcr3Documents.Where(d => d.CompletedByID <= 0).Count() > 0; bool approvalsIncomplete = currentStageApprovals.Count() > 0 && currentStagePendingApprovalsCount > 0; + IEnumerable currentStageAttendees = attendees.Where(a => a.Step == current_i); + bool atLeastOneAttendeeAttended = currentStageAttendees.Where(a => a.Attended == true).Count() > 0; + @@ -540,12 +533,6 @@ OnClick="@((e) => AddAttendee(current_i))"> Add Attendee - - Save Attendance - - + @@ -601,7 +589,7 @@ } @if (previousStageSubmitted && !currentStageSubmitted && currentStageAttachments.Count() > 0 && !affectedDocumentsIncomplete && allActionItemsComplete && - !previousStageHasOpenGatedActionItems) { + !previousStageHasOpenGatedActionItems && atLeastOneAttendeeAttended) { @if (submitInProcess) { Submitting @@ -687,1101 +675,4 @@ - - -@code { - [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 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"; - } -} \ No newline at end of file + \ No newline at end of file diff --git a/MesaFabApproval.Client/Pages/PCRBSingle.razor.cs b/MesaFabApproval.Client/Pages/PCRBSingle.razor.cs new file mode 100644 index 0000000..55d3f02 --- /dev/null +++ b/MesaFabApproval.Client/Pages/PCRBSingle.razor.cs @@ -0,0 +1,1139 @@ +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"; + } +}