@page "/mrb/{mrbNumber}" @page "/mrb/new" @using System.Text @inject IMRBService mrbService @inject ISnackbar snackbar @inject IDialogService dialogService @inject NavigationManager navigationManager @inject MesaFabApprovalAuthStateProvider authStateProvider @inject IUserService userService @inject IMemoryCache cache @inject IConfiguration config @inject IApprovalService approvalService @if (mrbNumber is not null) { MRB @mrbNumber MRB @mrbNumber } @if (mrb is not null) { @for (int i = 0; i < MRB.Stages.Length; i++) { Color color; if (mrb.StageNo > i || mrb.StageNo == (MRB.Stages.Length - 1)) { color = Color.Success; } else if (mrb.StageNo == i) { color = Color.Info; } else { color = Color.Dark; } string stageName = MRB.Stages[i]; @stageName } bool mrbIsSubmitted = mrb.SubmittedDate > DateTime.MinValue; bool mrbReadyToSubmit = mrbIsReadyToSubmit(); bool userIsApprover = currentUserIsApprover(); if (!mrbIsSubmitted || (!mrbIsSubmitted && mrbReadyToSubmit) || (mrbIsSubmitted && userIsApprover)) { @if (!mrbIsSubmitted) { @if (saveInProcess) { Processing } else { Save } } @if (!mrbIsSubmitted && mrbReadyToSubmit) { @if (submitInProcess) { Processing } else { Submit for Approval } } @if (mrbIsSubmitted && userIsApprover) { Approve Deny } } @if (mrb is not null && mrb.CancelDate < DateTime.MaxValue) { } DateTime.MinValue) @bind-Value=mrb.OriginatorName Text="@mrb.OriginatorName"> @foreach (User user in allActiveUsers) { } DateTime.MinValue) @bind-Value=mrb.Department Text="@mrb.Department"> DateTime.MinValue) @bind-Value=mrb.Process Text="@mrb.Process"> } @if (mrb is not null && mrb.MRBNumber > 0) { Supporting Documents @if (!(mrb.SubmittedDate > DateTime.MinValue)) { Upload Document } @if (mrbAttachments is not null) { Name Upload Date @context.FileName @context.UploadDate.ToString("yyyy-MM-dd HH:mm") @if (mrb is not null && !(mrb.SubmittedDate > DateTime.MinValue)) { @if (deleteActionInProcess) { Deleting } else { Delete } } } Actions @if (!(mrb.SubmittedDate > DateTime.MinValue)) { Create New Action } @if (mrbActions is not null) { Action Customer Qty Part Number Batch Number / Lot Number Assigned Date Completed Date Completed By @context.Action @context.Customer @context.Quantity @context.PartNumber @context.LotNumber @DateTimeUtilities.GetDateAsStringMinDefault(context.AssignedDate) @DateTimeUtilities.GetDateAsStringMaxDefault(context.CompletedDate) @context.CompletedByUser?.GetFullName() @if (mrb is not null && !(mrb.SubmittedDate > DateTime.MinValue)) { Edit @if (deleteActionInProcess) { Deleting } else { Delete } } @if (currentUser is not null && taskApprovals.Where(t => t.UserID == currentUser.UserID && t.TaskID == context.ActionID).ToList().Count() > 0 && context.CompletedDate >= DateTime.MaxValue) { Mark Complete } } Approvals @if (nonTaskApprovals is not null) { Role Approver Name Status Disposition Date Comments @context.SubRoleCategoryItem @context.User?.GetFullName() @context.StatusMessage @DateTimeUtilities.GetDateAsStringMaxDefault(context.CompletedDate) @context.Comments } } @code { [Parameter] public string? mrbNumber { get; set; } private int mrbNumberInt = 0; private MRB? mrb { get; set; } private User? currentUser = null; private int currentUserId = 0; private IEnumerable allActiveUsers = new List(); private IEnumerable mrbActions = new List(); private IEnumerable mrbAttachments = new List(); private IEnumerable mrbApprovals = new List(); private IEnumerable nonTaskApprovals = new List(); private IEnumerable taskApprovals = new List(); private bool processing = false; private bool saveInProcess = false; private bool submitInProcess = false; private bool approvalInProcess = false; private bool taskApprovalInProcess = false; private bool denialInProcess = false; private bool deleteActionInProcess = false; private bool deleteAttachmentInProcess = false; private string actionSearchString = ""; private string attachmentSearchString = ""; private string currentUrl = ""; protected override async Task OnParametersSetAsync() { processing = true; try { if (allActiveUsers is null) allActiveUsers = await userService.GetAllActiveUsers(); if (authStateProvider is not null) currentUser = authStateProvider.CurrentUser; if (navigationManager is not null) currentUrl = navigationManager.Uri; if (!string.IsNullOrWhiteSpace(mrbNumber) && Int32.TryParse(mrbNumber, out mrbNumberInt)) { mrb = await mrbService.GetMRBById(mrbNumberInt); mrbActions = await mrbService.GetMRBActionsForMRB(mrbNumberInt, false); mrbAttachments = await mrbService.GetAllAttachmentsForMRB(mrbNumberInt, false); mrbApprovals = await approvalService.GetApprovalsForIssueId(mrbNumberInt, false); nonTaskApprovals = mrbApprovals.Where(a => a.Step < 3).ToList(); taskApprovals = mrbApprovals.Where(a => a.Step >= 3).ToList(); } else { mrbNumberInt = 0; mrbNumber = ""; mrb = new() { Status = "Draft", StageNo = 0 }; mrbActions = new List(); mrbAttachments = new List(); mrbApprovals = new List(); nonTaskApprovals = new List(); taskApprovals = new List(); if (authStateProvider is not null && authStateProvider.CurrentUser is not null) { mrb.OriginatorID = authStateProvider.CurrentUser.UserID; mrb.OriginatorName = $"{authStateProvider.CurrentUser.FirstName} {authStateProvider.CurrentUser.LastName}"; } } } catch (Exception ex) { snackbar.Add(ex.Message, Severity.Error); } processing = false; } private void ReturnToAllMrbs() { cache.Set("redirectUrl", $"mrb/all"); navigationManager.NavigateTo("mrb/all"); } private async void SaveMRB() { try { saveInProcess = true; MRB initialMrb = new MRB() { MRBNumber = mrb.MRBNumber, Status = mrb.Status, StageNo = 0 }; if (mrb is not null) { User? originator = allActiveUsers.Where(u => $"{u.FirstName} {u.LastName}".Equals(mrb.OriginatorName)).FirstOrDefault(); if (originator is not null) mrb.OriginatorID = originator.UserID; if (mrb.MRBNumber <= 0) { await mrbService.CreateNewMRB(mrb); mrb = await mrbService.GetMRBByTitle(mrb.Title, true); cache.Set("redirectUrl", $"mrb/{mrb.MRBNumber}"); } else { await mrbService.UpdateMRB(mrb); } mrbNumber = mrb.MRBNumber.ToString(); mrbNumberInt = mrb.MRBNumber; foreach (MRBAction action in mrbActions) { if (action is not null) { action.MRBNumber = mrbNumberInt; if (action.ActionID > 0) { await mrbService.UpdateMRBAction(action); } else { await mrbService.CreateMRBAction(action); } } } mrbActions = await mrbService.GetMRBActionsForMRB(mrbNumberInt, true); } saveInProcess = false; StateHasChanged(); snackbar.Add($"MRB {mrb.MRBNumber} successfully saved", Severity.Success); if (initialMrb.MRBNumber <= 0) navigationManager.NavigateTo($"mrb/{mrb.MRBNumber}"); } catch (Exception ex) { saveInProcess = false; snackbar.Add(ex.Message, Severity.Error); } saveInProcess = false; } private async void SubmitMRBForApproval() { submitInProcess = true; try { if (mrb is null) throw new Exception("MRB cannot be null"); User? originator = allActiveUsers.Where(u => $"{u.FirstName} {u.LastName}".Equals(mrb.OriginatorName)).FirstOrDefault(); if (originator is not null) mrb.OriginatorID = originator.UserID; if (mrb.StageNo == 0) { mrb.StageNo++; mrb.SubmittedDate = DateTime.Now; await mrbService.UpdateMRB(mrb); } foreach (MRBAction action in mrbActions) { if (action is not null) { action.MRBNumber = mrb.MRBNumber; if (action.ActionID > 0) { await mrbService.UpdateMRBAction(action); } else { await mrbService.CreateMRBAction(action); } } } mrbActions = await mrbService.GetMRBActionsForMRB(mrbNumberInt, true); await mrbService.SubmitForApproval(mrb); await mrbService.NotifyNewApprovals(mrb); mrbApprovals = await approvalService.GetApprovalsForIssueId(mrb.MRBNumber, true); nonTaskApprovals = mrbApprovals.Where(a => a.Step < 3).ToList(); taskApprovals = mrbApprovals.Where(a => a.Step >= 3).ToList(); submitInProcess = false; snackbar.Add("MRB submitted for approval", Severity.Success); } catch (Exception ex) { submitInProcess = false; snackbar.Add($"Unable to submit MRB for approval, because {ex.Message}", Severity.Error); } StateHasChanged(); } private async void ApproveMRB() { approvalInProcess = true; try { if (mrbApprovals is null || mrbApprovals.Count() <= 0) throw new Exception("there are no approvals to approval"); if (authStateProvider.CurrentUser is null) { navigationManager.NavigateTo("login"); return; } if (mrb is null) throw new Exception("MRB is null"); string? comments = ""; DialogParameters parameters = new DialogParameters { { x => x.comments, comments } }; var dialog = dialogService.Show($"Approval Comments", parameters); var result = await dialog.Result; comments = result.Data.ToString(); if (result.Canceled) throw new Exception("you must provide your approval comments"); IEnumerable approvals = mrbApprovals.Where(a => a.UserID == authStateProvider.CurrentUser.UserID && !(a.CompletedDate < DateTime.MaxValue) && a.Step == mrb.StageNo); foreach (Approval approval in approvals) { approval.CompletedDate = DateTime.Now; approval.Comments = comments is null ? "" : comments; approval.ItemStatus = 1; await approvalService.Approve(approval); } IEnumerable remainingApprovalsInKind = approvals.Where(a => a.Step == mrb.StageNo && a.UserID != authStateProvider.CurrentUser.UserID && !(a.CompletedDate < DateTime.MaxValue)); if (remainingApprovalsInKind is null || remainingApprovalsInKind.Count() <= 0) { mrb.StageNo++; if (mrb.StageNo == 3) mrb.ApprovalDate = DateTime.Now; await mrbService.UpdateMRB(mrb); if (mrb.StageNo < 3) SubmitMRBForApproval(); if (mrb.StageNo == 3) { GenerateActionTasks(); string body = $"Your MRB ({mrb.MRBNumber}) has been approved."; MRBNotification notification = new() { MRB = mrb, Message = body }; await mrbService.NotifyOriginator(notification); } } mrbActions = await mrbService.GetMRBActionsForMRB(mrb.MRBNumber, true); mrbApprovals = await approvalService.GetApprovalsForIssueId(mrb.MRBNumber, true); taskApprovals = mrbApprovals.Where(a => a.Step >= 3).ToList(); nonTaskApprovals = mrbApprovals.Where(a => a.Step < 3).ToList(); approvalInProcess = false; StateHasChanged(); snackbar.Add("Successfully approved", Severity.Success); } catch (Exception ex) { approvalInProcess = false; snackbar.Add($"Unable to approve, because {ex.Message}", Severity.Error); } } private async void DenyMRB() { denialInProcess = true; try { if (mrbApprovals is null || mrbApprovals.Count() <= 0) throw new Exception("there are no approvals to deny"); if (authStateProvider.CurrentUser is null) { navigationManager.NavigateTo("login"); return; } if (mrb is null) throw new Exception("MRB is null"); string? comments = ""; DialogParameters parameters = new DialogParameters { { x => x.comments, comments } }; var dialog = dialogService.Show($"Denial Comments", parameters); var result = await dialog.Result; comments = result.Data.ToString(); if (result.Canceled) throw new Exception("you must provide your denial comments"); IEnumerable approvals = mrbApprovals.Where(a => a.UserID == authStateProvider.CurrentUser.UserID && !(a.CompletedDate < DateTime.MaxValue) && a.Step == mrb.StageNo); foreach (Approval approval in approvals) { approval.CompletedDate = DateTime.Now; approval.Comments = comments is null ? "" : comments; approval.ItemStatus = -1; await approvalService.Deny(approval); } if (mrb.StageNo < 2) { mrb.StageNo = 0; mrb.SubmittedDate = DateTime.MinValue; } else { IEnumerable remainingApprovalsInKind = approvals.Where(a => a.Step == mrb.StageNo && a.UserID != authStateProvider.CurrentUser.UserID && !(a.CompletedDate < DateTime.MaxValue)); if (remainingApprovalsInKind is null || remainingApprovalsInKind.Count() <= 0) { mrb.CloseDate = DateTime.Now; } } await mrbService.UpdateMRB(mrb); mrbApprovals = await approvalService.GetApprovalsForIssueId(mrb.MRBNumber, true); nonTaskApprovals = mrbApprovals.Where(a => a.Step < 3).ToList(); string body = $"Your MRB ({mrb.MRBNumber}) has been denied."; MRBNotification notification = new() { MRB = mrb, Message = body }; await mrbService.NotifyOriginator(notification); denialInProcess = false; StateHasChanged(); snackbar.Add("Successfully approved", Severity.Success); } catch (Exception ex) { denialInProcess = false; snackbar.Add($"Unable to approve, because {ex.Message}", Severity.Error); } } private async void GenerateActionTasks() { try { if (mrb is null) throw new Exception("MRB cannot be null"); foreach (MRBAction action in mrbActions) { action.AssignedDate = DateTime.Now; await mrbService.UpdateMRBAction(action); await mrbService.GenerateActionTasks(mrb, action); } await mrbService.NotifyNewApprovals(mrb); } catch (Exception ex) { snackbar.Add($"Unable to generate action tasks, because {ex.Message}", Severity.Error); } } private async void CompleteAction(MRBAction action) { try { if (action is null) throw new Exception("MRB action cannot be null"); if (authStateProvider.CurrentUser is null) throw new Exception("you must be logged in to complete this action"); if (mrb is null) throw new Exception("MRB cannot be null"); action.CompletedDate = DateTime.Now; action.CompletedByUserID = authStateProvider.CurrentUser.UserID; action.CompletedByUser = authStateProvider.CurrentUser; await mrbService.UpdateMRBAction(action); mrbActions = await mrbService.GetMRBActionsForMRB(action.MRBNumber, true); string role = ""; foreach (Approval approval in taskApprovals) { bool approved = false; if (approval.UserID == action.CompletedByUserID && approval.ItemStatus == 0 && approval.TaskID == action.ActionID) { approved = true; role = approval.SubRoleCategoryItem; await approvalService.Approve(approval); } if (!approved && approval.SubRoleCategoryItem.Equals(role)) await approvalService.Approve(approval); } mrbApprovals = await approvalService.GetApprovalsForIssueId(mrb.MRBNumber, true); taskApprovals = mrbApprovals.Where(a => a.Step >= 3).ToList(); int outStandingTaskCount = taskApprovals.Where(a => a.CompletedDate >= DateTime.MaxValue).Count(); if (outStandingTaskCount == 0) { mrb.StageNo++; mrb.CloseDate = DateTime.Now; await mrbService.UpdateMRB(mrb); string body = $"Your MRB ({mrb.MRBNumber}) is complete."; MRBNotification notification = new() { MRB = mrb, Message = body }; await mrbService.NotifyOriginator(notification); } StateHasChanged(); } catch (Exception ex) { snackbar.Add($"Unable to mark action complete, because {ex.Message}", Severity.Error); } } private bool mrbIsReadyToSubmit() { return mrb is not null && !(mrb.SubmittedDate > DateTime.MinValue) && mrb.MRBNumber > 0 && mrb.OriginatorID > 0 && !mrb.OriginatorName.Equals("") && !mrb.Title.Equals("") && !mrb.IssueDescription.Equals("") && !mrb.Department.Equals("") && !mrb.Process.Equals(""); } private bool currentUserIsApprover() { if (mrbApprovals is null || authStateProvider is null) return false; if (authStateProvider.CurrentUser is null) return false; IEnumerable approvalsForCurrentUser = mrbApprovals.Where(a => mrb is not null && mrb.StageNo < 3 && a.UserID == authStateProvider.CurrentUser.UserID && a.ItemStatus == 0); if (approvalsForCurrentUser is not null && approvalsForCurrentUser.Count() > 0) return true; return false; } private async void CreateNewAction() { try { MRBAction mrbAction = new() { Action = "", Customer = "", LotNumber = "", PartNumber = "", MRBNumber = mrbNumberInt, Quantity = 0 }; DialogParameters parameters = new DialogParameters { { x => x.mrbAction, mrbAction } }; var dialog = dialogService.Show($"New MRB Action", parameters); var result = await dialog.Result; if (!result.Canceled) { if (mrbNumberInt > 0) { mrbActions = await mrbService.GetMRBActionsForMRB(mrbNumberInt, true); } else { List actionList = mrbActions.ToList(); actionList.Add(mrbAction); mrbActions = actionList; } StateHasChanged(); } } catch (Exception ex) { snackbar.Add(ex.Message, Severity.Error); } } private async void EditAction(MRBAction mrbAction) { try { if (mrbAction is null) throw new ArgumentNullException("Action cannot be null"); var parameters = new DialogParameters { { x => x.mrbAction, mrbAction } }; var dialog = dialogService.Show($"MRB Action {mrbAction.ActionID}", parameters); var result = await dialog.Result; if (!result.Canceled) { if (mrbNumberInt > 0) { mrbActions = await mrbService.GetMRBActionsForMRB(mrbNumberInt, true); } else { List actionList = mrbActions.ToList(); actionList.Add(mrbAction); mrbActions = actionList; } StateHasChanged(); } } catch (Exception ex) { snackbar.Add(ex.Message, Severity.Error); } } private async void DeleteAction(MRBAction mrbAction) { deleteActionInProcess = true; try { if (mrbAction is null) throw new ArgumentNullException("Action cannot be null"); await mrbService.DeleteMRBAction(mrbAction); List mrbActionList = mrbActions.ToList(); mrbActionList.RemoveAll(x => x.ActionID == mrbAction.ActionID); mrbActions = mrbActionList; snackbar.Add("Action successfully deleted", Severity.Success); } catch (Exception ex) { snackbar.Add(ex.Message, Severity.Error); } deleteActionInProcess = false; StateHasChanged(); } private bool FilterFuncForMRBActionTable(MRBAction action) => MRBActionFilterFunc(action, actionSearchString); private bool MRBActionFilterFunc(MRBAction action, string searchString) { if (string.IsNullOrWhiteSpace(searchString)) return true; string search = searchString.ToLower(); if (action.Customer.ToLower().Contains(search)) return true; if (action.Action.ToLower().Contains(search)) return true; if (action.PartNumber.ToLower().Contains(search)) return true; if (action.LotNumber.ToLower().Contains(search)) return true; return false; } private async Task AddAttachments(InputFileChangeEventArgs args) { List attachments = new() { args.File }; if (authStateProvider.CurrentUser is not null) { await mrbService.UploadAttachments(attachments, mrbNumberInt); mrbAttachments = await mrbService.GetAllAttachmentsForMRB(mrbNumberInt, true); StateHasChanged(); } } private async void DeleteAttachment(MRBAttachment mrbAttachment) { deleteAttachmentInProcess = true; try { if (mrbAttachment is null) throw new ArgumentNullException("Attachment cannot be null"); await mrbService.DeleteAttachment(mrbAttachment); List mrbAttachmentList = mrbAttachments.ToList(); mrbAttachmentList.RemoveAll(x => x.AttachmentID == mrbAttachment.AttachmentID); mrbAttachments = mrbAttachmentList; snackbar.Add("Attachment successfully deleted", Severity.Success); } catch (Exception ex) { snackbar.Add(ex.Message, Severity.Error); } deleteAttachmentInProcess = false; StateHasChanged(); } private bool FilterFuncForMRBAttachmentTable(MRBAttachment attachment) => MRBAttachmentFilterFunc(attachment, attachmentSearchString); private bool MRBAttachmentFilterFunc(MRBAttachment attachment, string searchString) { if (string.IsNullOrWhiteSpace(searchString)) return true; string search = searchString.ToLower(); if (attachment.FileName.ToLower().Contains(search)) return true; return false; } }