@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
@inject IDialogService dialogService
@inject IPCRBService pcrbService
@inject IECNService ecnService
@inject ICustomerService customerService
@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 > DateTimeUtilities.MIN_DT;
bool mrbReadyToSubmit = mrbIsReadyToSubmit();
bool userIsApprover = currentUserIsApprover();
bool approvalsArePending = false;
foreach (Approval approval in nonTaskApprovals) {
if (approval.ItemStatus == 0) approvalsArePending = true;
}
bool userIsOriginator = mrb.OriginatorID == authStateProvider.CurrentUser?.UserID;
bool userIsAdmin = authStateProvider.CurrentUser is null ? false : authStateProvider.CurrentUser.IsAdmin;
bool mrbNumberIsValid = mrb is null ? false : mrb.MRBNumber > 0;
User? currentUser = authStateProvider.CurrentUser;
if ((!mrbIsSubmitted && !string.IsNullOrWhiteSpace(mrb.Title)) ||
(!mrbIsSubmitted && mrbNumberIsValid && (userIsOriginator || userIsAdmin)) ||
(!mrbIsSubmitted && mrbReadyToSubmit && (userIsOriginator || userIsAdmin)) ||
(mrbIsSubmitted && userIsApprover && approvalsArePending) ||
((userIsOriginator || userIsAdmin) && mrb.StageNo > 0 && mrb.StageNo < 4)) {
@if (!mrbIsSubmitted && !string.IsNullOrWhiteSpace(mrb.Title)) {
@if (saveInProcess) {
Processing
} else {
Save
}
}
@if (!mrbIsSubmitted && mrbNumberIsValid && (userIsOriginator || userIsAdmin)) {
@if (deleteInProcess) {
Processing
} else {
Delete
}
}
@if (!mrbIsSubmitted && mrbReadyToSubmit && (userIsOriginator || userIsAdmin)) {
@if (submitInProcess) {
Processing
} else {
Submit for Approval
}
}
@if (mrbIsSubmitted && userIsApprover && approvalsArePending) {
@if (approvalInProcess) {
Processing
} else {
Approve
}
@if (denialInProcess) {
Processing
} else {
Deny
}
}
@if ((userIsOriginator || userIsAdmin) && mrb.StageNo > 0 && mrb.StageNo < 4) {
@if (recallInProcess) {
Processing
} else {
Recall
}
}
}
@if (!mrbIsSubmitted && GetIncompleteFields().Count() > 0) {
IEnumerable incompleteFields = GetIncompleteFields();
StringBuilder errorBuilder = new();
errorBuilder.Append($"Incomplete fields: {incompleteFields.First()}");
for (int i = 1; i < incompleteFields.Count(); i++) {
errorBuilder.Append($", {incompleteFields.ElementAt(i)}");
}
@errorBuilder.ToString()
}
@if (mrb is not null && mrb.CancelDate < DateTimeUtilities.MAX_DT) {
}
DateTimeUtilities.MIN_DT)
@bind-Value=mrb.OriginatorName
Text="@mrb.OriginatorName">
@foreach (User user in allActiveUsers.OrderBy(u => u.LastName)) {
}
DateTimeUtilities.MIN_DT)
@bind-Value=mrb.Category
Text="@mrb.Category">
DateTimeUtilities.MIN_DT)
ValueChanged="@DepartmentChanged"
Text="@mrb.Department">
DateTimeUtilities.MIN_DT)
ValueChanged="@ProcessChanged"
Text="@mrb.Process">
@if (mrb.Department.Equals("Production")) {
foreach (Process process in Process.ProductionProcesses) {
}
} else if (mrb.Department.Equals("Engineering")) {
foreach (Process process in Process.EngineeringProcesses) {
}
} else if (mrb.Department.Equals("Materials")) {
foreach (Process process in Process.MaterialsProcesses) {
}
} else if (mrb.Department.Equals("Facilities")) {
foreach (Process process in Process.FacilitiesProcesses) {
}
} else if (mrb.Department.Equals("Maintenance")) {
foreach (Process process in Process.MaintenanceProcesses) {
}
} else if (mrb.Department.Equals("Quality")) {
foreach (Process process in Process.QualityProcesses) {
}
}
@if (mrb.Process.Equals("Reactor") ||
mrb.Process.Equals("Metrology") ||
mrb.Process.Equals("Cleans") ||
mrb.Process.Equals("Packaging") ||
mrb.Process.Equals("Final QA")) {
DateTimeUtilities.MIN_DT)
Text="@mrb.Tool"
@bind-Value=mrb.Tool
>
@if (mrb.Process.Equals("Reactor")) {
@foreach (Tool tool in Tool.ReactorTools) {
}
}
@if (mrb.Process.Equals("Metrology")) {
@foreach (Tool tool in Tool.MetrologyTools) {
}
}
@if (mrb.Process.Equals("Cleans")) {
@foreach (Tool tool in Tool.CleansTools) {
}
}
@if (mrb.Process.Equals("Packaging")) {
@foreach (Tool tool in Tool.PackagingTools) {
}
}
@if (mrb.Process.Equals("Final QA")) {
@foreach (Tool tool in Tool.FqaTools) {
}
}
}
@if (mrb.SpecsImpacted) {
}
@if (mrb.CustomerImpacted) {
DateTimeUtilities.MIN_DT)
@bind-Value=mrb.CustomerImpactedName
Text="@mrb.CustomerImpactedName">
@foreach (string customer in customerNames) {
}
}
}
@if (mrb is not null && mrb.MRBNumber > 0) {
Supporting Documents
@if (!(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)) {
@if (attachmentUploadInProcess) {
Processing
} else {
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 > DateTimeUtilities.MIN_DT)) {
@if (deleteActionInProcess) {
Deleting
} else {
Delete
}
}
}
Actions
@if (!(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)) {
Create New Action
}
@if (mrb.SubmittedDate > DateTimeUtilities.MIN_DT && mrb.StageNo == 3 &&
(currentUser?.UserID == mrb.OriginatorID || currentUser?.IsAdmin == true)) {
@if (completeAllActionsInProcess) {
Processing
} else {
Complete All Actions
}
}
@if (mrbActions is not null) {
Download as CSV File
Action
Customer
Qty
Part Number
Batch Number / Lot Number
Justification
Assigned Date
Completed Date
Completed By
Comments
Attachments
@if (context.Action.ToLower().Equals("convert")) {
@context.Action @context.ConvertFrom to @context.ConvertTo
} else {
@context.Action
}
@context.Customer
@context.Quantity
@context.PartNumber
@context.LotNumber
@context.Justification
@DateTimeUtilities.GetDateAsStringMinDefault(context.AssignedDate)
@DateTimeUtilities.GetDateAsStringMaxDefault(context.CompletedDate)
@context.CompletedByUser?.GetFullName()
@if (taskApprovals.Where(t => t.TaskID == context.ActionID).Count() > 0) {
Approval? approval = taskApprovals.Where(t => t.TaskID == context.ActionID).FirstOrDefault();
if (approval is not null) {
@approval.Comments
} else {
@string.Empty
}
}
@if (mrbActionAttachments.Where(a => a.ActionID == context.ActionID).Count() > 0) {
IEnumerable attachments = mrbActionAttachments.Where(a => a.ActionID == context.ActionID).ToList();
foreach (MRBActionAttachment attachment in attachments) {
}
}
@if (mrb is not null && !(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)) {
Edit
@if (deleteActionInProcess) {
Deleting
} else {
Delete
}
}
@if (currentUser is not null && taskApprovals.Where(t => t.CompletedDate > DateTime.Now &&
t.UserID == currentUser.UserID &&
t.TaskID == context.ActionID).ToList().Count() > 0 &&
context.CompletedDate >= DateTimeUtilities.MAX_DT) {
Mark Complete
}
}
bool mrbIsSubmitted = mrb.SubmittedDate > DateTimeUtilities.MIN_DT;
bool mrbReadyToSubmit = mrbIsReadyToSubmit();
bool userIsOriginator = mrb.OriginatorID == authStateProvider.CurrentUser?.UserID;
bool userIsAdmin = authStateProvider.CurrentUser is null ? false : authStateProvider.CurrentUser.IsAdmin;
Approvals
@if (!mrbIsSubmitted && mrbReadyToSubmit && (userIsOriginator || userIsAdmin)) {
@if (submitInProcess) {
Processing
} else {
Submit for Approval
}
}
@if (nonTaskApprovals is not null) {
Role
Approver Name
Status
Assigned Date
Disposition Date
Comments
@context.SubRoleCategoryItem
@context.User?.GetFullName()
@context.StatusMessage
@DateTimeUtilities.GetDateAsStringMaxDefault(context.AssignedDate)
@DateTimeUtilities.GetDateAsStringMaxDefault(context.CompletedDate)
@context.Comments
@if (context.ItemStatus == 0 && authStateProvider.CurrentUser is not null && authStateProvider.CurrentUser.IsAdmin) {
Reassign
}
}
}
@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 mrbActionAttachments = new List();
private IEnumerable mrbAttachments = new List();
private IEnumerable mrbApprovals = new List();
private IEnumerable nonTaskApprovals = new List();
private IEnumerable taskApprovals = new List();
private IEnumerable customerNames = new List();
private IEnumerable partNumbers = new List();
private IEnumerable lotNumbers = new List();
private bool processing = false;
private bool saveInProcess = false;
private bool submitInProcess = false;
private bool deleteInProcess = false;
private bool recallInProcess = false;
private bool approvalInProcess = false;
private bool taskApprovalInProcess = false;
private bool denialInProcess = false;
private bool completeAllActionsInProcess = false;
private bool deleteActionInProcess = false;
private bool attachmentUploadInProcess = false;
private bool deleteAttachmentInProcess = false;
private string actionSearchString = "";
private string attachmentSearchString = "";
private string currentUrl = "";
private MudTextField? processEcnField;
private bool processEcnIsValid = false;
private MudTextField? pcrbNoField;
private bool pcrbNoIsValid = false;
protected override async Task OnParametersSetAsync() {
processing = true;
try {
allActiveUsers = await userService.GetAllActiveUsers();
currentUser = authStateProvider.CurrentUser;
currentUrl = navigationManager.Uri;
if (!string.IsNullOrWhiteSpace(mrbNumber) && Int32.TryParse(mrbNumber, out mrbNumberInt)) {
mrb = await mrbService.GetMRBById(mrbNumberInt);
if (mrb.ProcessECNNumber > 0) await ECNNoIsValid(mrb.ProcessECNNumber);
if (!string.IsNullOrWhiteSpace(mrb.PCRBNo)) await PCRBNoIsValid(mrb.PCRBNo);
mrbActions = await mrbService.GetMRBActionsForMRB(mrbNumberInt, false);
partNumbers = GetPartNumbers();
lotNumbers = GetLotNumbers();
mrb.NumberOfLotsAffected = GetTotalActionQuantities();
mrbActionAttachments = await mrbService.GetAllActionAttachmentsForMRB(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}";
}
}
if (customerNames is null || customerNames.Count() <= 0)
customerNames = (await customerService.GetAllCustomerNames()).OrderBy(c => c);
StateHasChanged();
} 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() {
if (!saveInProcess) {
try {
saveInProcess = true;
MRB initialMrb = new MRB() {
MRBNumber = mrb.MRBNumber,
Status = mrb.Status,
StageNo = 0,
NumberOfLotsAffected = 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}");
}
mrb.NumberOfLotsAffected = 0;
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);
}
mrb.NumberOfLotsAffected += action.Quantity;
}
}
if (mrb.MRBNumber > 0) await mrbService.UpdateMRB(mrb);
mrbNumber = mrb.MRBNumber.ToString();
mrbNumberInt = mrb.MRBNumber;
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 DeleteMRB() {
if (!deleteInProcess) {
try {
bool? result = await dialogService.ShowMessageBox(
"Warning",
$"Are you sure you want to delete MRB# {mrb.MRBNumber}?",
yesText: "Yes", noText: "No"
);
if (result == true) {
deleteInProcess = true;
await mrbService.DeleteMRB(mrb.MRBNumber);
deleteInProcess = false;
snackbar.Add("MRB successfully deleted", Severity.Success);
navigationManager.NavigateTo("mrb/all");
}
} catch (Exception ex) {
deleteInProcess = false;
snackbar.Add($"Unable to delete MRB, because {ex.Message}", Severity.Error);
}
}
}
private async void SubmitMRBForApproval() {
if (!submitInProcess && !processing) {
submitInProcess = true;
processing = 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;
}
mrb.NumberOfLotsAffected = 0;
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);
}
mrb.NumberOfLotsAffected += action.Quantity;
}
}
mrbActions = await mrbService.GetMRBActionsForMRB(mrbNumberInt, true);
await mrbService.UpdateMRB(mrb);
await mrbService.SubmitForApproval(mrb);
await mrbService.NotifyNewApprovals(mrb);
if (mrb.StageNo == 1) {
StringBuilder messageBuilder = new();
messageBuilder.Append($"MRB# {mrb.MRBNumber} [{mrb.Title}] has been submitted for approval. ");
messageBuilder.Append("You will receive an email after it has been approved.");
MRBNotification notification = new() {
MRB = mrb,
Message = messageBuilder.ToString()
};
await mrbService.NotifyOriginator(notification);
}
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;
processing = false;
snackbar.Add("MRB submitted for approval", Severity.Success);
} catch (Exception ex) {
submitInProcess = false;
processing = false;
snackbar.Add($"Unable to submit MRB for approval, because {ex.Message}", Severity.Error);
}
StateHasChanged();
}
}
private async void ApproveMRB() {
if (!approvalInProcess && !processing) {
approvalInProcess = true;
processing = true;
try {
if (mrb is null) throw new Exception("MRB is null");
mrbApprovals = await approvalService.GetApprovalsForIssueId(mrb.MRBNumber, true);
if (mrbApprovals is null || mrbApprovals.Count() <= 0)
throw new Exception("there are no approvals to approve");
if (authStateProvider.CurrentUser is null) {
navigationManager.NavigateTo("login");
return;
}
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();
IEnumerable approvals = mrbApprovals.Where(a => a.UserID == authStateProvider.CurrentUser.UserID &&
a.ItemStatus == 0 &&
!(a.CompletedDate < DateTimeUtilities.MAX_DT) &&
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 sameRoleApprovals = mrbApprovals.Where(a => a.Step == mrb.StageNo &&
!(a.UserID == authStateProvider.CurrentUser.UserID) &&
a.ItemStatus == 0 &&
a.SubRoleCategoryItem.ToLower().Equals(approval.SubRoleCategoryItem.ToLower()) &&
!(a.CompletedDate < DateTimeUtilities.MAX_DT));
foreach (Approval sameApp in sameRoleApprovals) {
sameApp.CompletedDate = DateTime.Now;
sameApp.Comments = comments is null ? "" : comments;
sameApp.ItemStatus = 1;
await approvalService.Approve(sameApp);
}
}
IEnumerable remainingApprovalsInKind = mrbApprovals.Where(a => a.Step == mrb.StageNo &&
a.ItemStatus == 0 &&
!(a.CompletedDate < DateTimeUtilities.MAX_DT));
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();
StringBuilder messageBuilder = new();
messageBuilder.Append($"MRB# {mrb.MRBNumber} [{mrb.Title}] has been approved. ");
messageBuilder.Append("You will receive an email when all actions are complete.");
MRBNotification notification = new() {
MRB = mrb,
Message = messageBuilder.ToString()
};
await mrbService.NotifyOriginator(notification);
string msg = $"MRB# {mrb.MRBNumber} [{mrb.Title}] has been approved.";
notification = new() {
MRB = mrb,
Message = msg
};
await mrbService.NotifyQAPreApprover(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();
if (mrb.StageNo == 3 && taskApprovals.Count() <= 0) {
mrb.StageNo++;
mrb.CloseDate = DateTime.Now;
await mrbService.UpdateMRB(mrb);
string body = $"MRB# {mrb.MRBNumber} [{mrb.Title}] is complete.";
MRBNotification notification = new() {
MRB = mrb,
Message = body
};
await mrbService.NotifyOriginator(notification);
await mrbService.NotifyQAPreApprover(notification);
snackbar.Add("MRB complete", Severity.Success);
}
approvalInProcess = false;
processing = false;
StateHasChanged();
snackbar.Add("Successfully approved", Severity.Success);
} catch (Exception ex) {
approvalInProcess = false;
processing = false;
snackbar.Add($"Unable to approve, because {ex.Message}", Severity.Error);
}
}
}
private async void RecallMRB() {
if (!recallInProcess) {
recallInProcess = true;
try {
if (mrb is null)
throw new Exception("MRB cannot be null");
User? currentUser = authStateProvider.CurrentUser;
if (currentUser is null) {
recallInProcess = false;
snackbar.Add("You must be logged in to recall this MRB", Severity.Error);
navigationManager.NavigateTo($"login/mrb/{mrb.MRBNumber}");
} else {
await mrbService.RecallMRB(mrb, currentUser);
mrbApprovals = await approvalService.GetApprovalsForIssueId(mrb.MRBNumber, true);
nonTaskApprovals = mrbApprovals.Where(a => a.Step < 3).ToList();
taskApprovals = mrbApprovals.Where(a => a.Step >= 3).ToList();
}
recallInProcess = false;
StateHasChanged();
snackbar.Add("MRB successfully recalled", Severity.Success);
} catch (Exception ex) {
recallInProcess = false;
snackbar.Add($"Unable to recall MRB, because {ex.Message}", Severity.Error);
throw;
}
}
}
private async void DenyMRB() {
if (!denialInProcess) {
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;
if (result.Canceled) throw new Exception("you must provide your denial comments");
comments = result.Data.ToString();
if (string.IsNullOrWhiteSpace(comments)) throw new Exception("you must provide your denial comments");
IEnumerable approvals = mrbApprovals.Where(a => !(a.CompletedDate < DateTimeUtilities.MAX_DT) &&
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);
}
mrb.StageNo = 0;
mrb.SubmittedDate = DateTimeUtilities.MIN_DT;
await mrbService.UpdateMRB(mrb);
mrbApprovals = await approvalService.GetApprovalsForIssueId(mrb.MRBNumber, true);
nonTaskApprovals = mrbApprovals.Where(a => a.Step < 3).ToList();
StringBuilder messageBuilder = new();
messageBuilder.AppendLine($"MRB# {mrb.MRBNumber} [{mrb.Title}] has been denied by {authStateProvider.CurrentUser.GetFullName()}. ");
messageBuilder.AppendLine("");
messageBuilder.Append($"Comments: {comments}");
MRBNotification notification = new() {
MRB = mrb,
Message = messageBuilder.ToString()
};
await mrbService.NotifyOriginator(notification);
mrbApprovals = await approvalService.GetApprovalsForIssueId(mrb.MRBNumber, true);
denialInProcess = false;
StateHasChanged();
snackbar.Add("Successfully denied", Severity.Success);
} catch (Exception ex) {
denialInProcess = false;
snackbar.Add($"Unable to process denial, 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) {
if (action.CompletedDate == DateTimeUtilities.MAX_DT) {
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");
string? comments = "";
DialogParameters parameters = new DialogParameters {
{ x => x.comments, comments },
{ x => x.actionId, action.ActionID} };
var dialog = dialogService.Show($"Completion Comments", parameters);
var result = await dialog.Result;
if (result.Canceled)
throw new Exception("you must provide your completion comments");
comments = result.Data.ToString();
if (string.IsNullOrWhiteSpace(comments))
throw new Exception("you must provide your completion comments");
action.CompletedDate = DateTime.Now;
action.CompletedByUserID = authStateProvider.CurrentUser.UserID;
action.CompletedByUser = authStateProvider.CurrentUser;
await mrbService.UpdateMRBAction(action);
mrbActions = await mrbService.GetMRBActionsForMRB(action.MRBNumber, true);
foreach (Approval approval in taskApprovals) {
if (approval.ItemStatus == 0 && approval.TaskID == action.ActionID) {
approval.Comments = comments;
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 >= DateTimeUtilities.MAX_DT).Count();
if (outStandingTaskCount == 0) {
mrb.StageNo++;
mrb.CloseDate = DateTime.Now;
await mrbService.UpdateMRB(mrb);
string body = $"MRB# {mrb.MRBNumber} [{mrb.Title}] is complete.";
MRBNotification notification = new() {
MRB = mrb,
Message = body
};
await mrbService.NotifyOriginator(notification);
await mrbService.NotifyQAPreApprover(notification);
snackbar.Add("All MRB actions complete", Severity.Success);
}
mrbActionAttachments = await mrbService.GetAllActionAttachmentsForMRB(action.MRBNumber, true);
StateHasChanged();
} catch (Exception ex) {
snackbar.Add($"Unable to mark action complete, because {ex.Message}", Severity.Error);
}
}
private async void CompleteAllActions() {
if (!completeAllActionsInProcess) {
try {
completeAllActionsInProcess = true;
if (mrbActions is null) throw new Exception("MRB actions 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");
string? comments = "";
MRBAction? firstAction = mrbActions.FirstOrDefault();
if (firstAction is null) throw new Exception("there are actions to complete");
DialogParameters parameters = new DialogParameters {
{ x => x.comments, comments },
{ x => x.actionId, firstAction.ActionID} };
var dialog = dialogService.Show($"Completion Comments", parameters);
var result = await dialog.Result;
if (result.Canceled)
throw new Exception("you must provide your completion comments");
comments = result.Data.ToString();
if (string.IsNullOrWhiteSpace(comments))
throw new Exception("you must provide your completion comments");
foreach (MRBAction action in mrbActions) {
action.CompletedDate = DateTime.Now;
action.CompletedByUserID = authStateProvider.CurrentUser.UserID;
action.CompletedByUser = authStateProvider.CurrentUser;
await mrbService.UpdateMRBAction(action);
mrbActions = await mrbService.GetMRBActionsForMRB(action.MRBNumber, true);
mrbActionAttachments = await mrbService.GetAllActionAttachmentsForMRB(action.MRBNumber, true);
}
foreach (Approval approval in taskApprovals) {
if (approval.ItemStatus == 0) {
approval.Comments = comments;
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 >= DateTimeUtilities.MAX_DT).Count();
if (outStandingTaskCount == 0) {
mrb.StageNo++;
mrb.CloseDate = DateTime.Now;
await mrbService.UpdateMRB(mrb);
string body = $"MRB# {mrb.MRBNumber} [{mrb.Title}] is complete.";
MRBNotification notification = new() {
MRB = mrb,
Message = body
};
await mrbService.NotifyOriginator(notification);
await mrbService.NotifyQAPreApprover(notification);
snackbar.Add("All MRB actions complete", Severity.Success);
}
completeAllActionsInProcess = false;
StateHasChanged();
} catch (Exception ex) {
completeAllActionsInProcess = false;
snackbar.Add($"Unable to mark action complete, because {ex.Message}", Severity.Error);
}
}
}
private bool mrbIsReadyToSubmit() {
bool isReadyToSubmit = mrb is not null &&
!(mrb.SubmittedDate > DateTimeUtilities.MIN_DT) &&
mrb.MRBNumber > 0 && mrb.OriginatorID > 0 &&
!string.IsNullOrWhiteSpace(mrb.OriginatorName) &&
!string.IsNullOrWhiteSpace(mrb.Title) &&
!string.IsNullOrWhiteSpace(mrb.Category) &&
mrb.Val > 0 &&
!string.IsNullOrWhiteSpace(mrb.IssueDescription) &&
!string.IsNullOrWhiteSpace(mrb.Department) &&
!string.IsNullOrWhiteSpace(mrb.Process) &&
(!mrb.CustomerImpacted || !string.IsNullOrWhiteSpace(mrb.CustomerImpactedName)) &&
(!mrb.SpecsImpacted || processEcnIsValid) &&
(string.IsNullOrWhiteSpace(mrb.PCRBNo) || pcrbNoIsValid);
if (mrb is not null && !mrb.Category.Equals("Material Transfer")) {
isReadyToSubmit = isReadyToSubmit && mrbActions is not null && mrbActions.Count() > 0;
isReadyToSubmit = isReadyToSubmit && mrb.NumberOfLotsAffected > 0;
}
isReadyToSubmit = isReadyToSubmit && mrbAttachments is not null && mrbAttachments.Count() > 0;
return isReadyToSubmit;
}
private IEnumerable GetIncompleteFields() {
List incompleteFields = new();
if (string.IsNullOrWhiteSpace(mrb.Title))
incompleteFields.Add("Title");
if (string.IsNullOrWhiteSpace(mrb.IssueDescription))
incompleteFields.Add("Description");
if (string.IsNullOrWhiteSpace(mrb.OriginatorName))
incompleteFields.Add("Originator");
if (string.IsNullOrWhiteSpace(mrb.Category))
incompleteFields.Add("Category");
if (string.IsNullOrWhiteSpace(mrb.Department))
incompleteFields.Add("Department");
if (string.IsNullOrWhiteSpace(mrb.Process))
incompleteFields.Add("Process");
if (mrb.Val <= 0) incompleteFields.Add("Value");
if (mrb.SpecsImpacted && (processEcnField is null || processEcnField.HasErrors))
incompleteFields.Add("Process ECN#");
if (mrb.CustomerImpacted && string.IsNullOrWhiteSpace(mrb.CustomerImpactedName))
incompleteFields.Add("Affected Customer");
return incompleteFields;
}
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) {
if (!deleteActionInProcess) {
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) {
if (!attachmentUploadInProcess) {
attachmentUploadInProcess = true;
try {
IReadOnlyList attachments = args.GetMultipleFiles();
if (authStateProvider.CurrentUser is not null) {
await mrbService.UploadAttachments(attachments, mrbNumberInt);
mrbAttachments = await mrbService.GetAllAttachmentsForMRB(mrbNumberInt, true);
attachmentUploadInProcess = false;
StateHasChanged();
}
} catch (Exception ex) {
attachmentUploadInProcess = false;
snackbar.Add($"Unable to upload attachments, because {ex.Message}", Severity.Error);
}
}
}
private async void DeleteAttachment(MRBAttachment mrbAttachment) {
if (!deleteAttachmentInProcess) {
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 async Task SpecsImpactedChanged(bool newValue) {
if (mrb is not null) {
mrb.SpecsImpacted = newValue;
if (!newValue) mrb.ProcessECNNumber = 0;
StateHasChanged();
}
}
private async Task CustomerImpactedChanged(bool newValue) {
if (mrb is not null) {
mrb.CustomerImpacted = newValue;
if (!newValue) mrb.CustomerImpactedName = "";
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;
}
private async Task PCRBNoIsValid(string id) {
string? result = await pcrbService.IdIsValid(id);
if (result is null) pcrbNoIsValid = true;
else pcrbNoIsValid = false;
StateHasChanged();
return result;
}
private async Task ECNNoIsValid(int ecnNumber) {
string? result = await ecnService.ECNNumberIsValidStr(ecnNumber);
if (result is null) processEcnIsValid = true;
else processEcnIsValid = false;
StateHasChanged();
return result;
}
private async Task ReassignApproval(Approval approval) {
try {
if (approval is null) throw new ArgumentNullException("approval cannot be null");
if (approval.CompletedDate < DateTimeUtilities.MAX_DT || approval.ItemStatus != 0)
throw new ArgumentException("cannot reassign a complete approval");
User? selectedUser = null;
DialogParameters parameters = new DialogParameters { { x => x.selectedUser, selectedUser } };
var dialog = dialogService.Show($"Select a new approver", parameters);
var result = await dialog.Result;
if (!result.Canceled) {
selectedUser = (User)result.Data;
}
if (selectedUser is null) throw new Exception("you must select a new approver");
if (selectedUser.UserID == approval.UserID)
throw new Exception("new approver must be different from current approver");
await SetUserForApproval(approval, selectedUser);
snackbar.Add($"Successfully reassigned approval", Severity.Success);
} catch (Exception ex) {
snackbar.Add($"Unable to reassign approval, because {ex.Message}", Severity.Error);
}
}
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);
MRB mrb = await mrbService.GetMRBById(approval.IssueID, true);
await mrbService.NotifyNewApprovals(mrb);
}
private int GetTotalActionQuantities() {
int total = 0;
foreach (MRBAction action in mrbActions) {
total += action.Quantity;
}
return total;
}
private IEnumerable GetPartNumbers() {
HashSet partNumbers = new();
foreach (MRBAction action in mrbActions) {
partNumbers.Add(action.PartNumber);
}
return partNumbers;
}
private IEnumerable GetLotNumbers() {
HashSet lotNumbers = new();
foreach (MRBAction action in mrbActions) {
lotNumbers.Add(action.LotNumber);
}
return lotNumbers;
}
private async Task> ToolSearch(string value, CancellationToken token) {
IEnumerable matchingTools =
Tool.FqaTools.Where(t => t.Name.Contains(value, StringComparison.InvariantCultureIgnoreCase));
HashSet toolNames = new();
foreach (Tool tool in matchingTools)
toolNames.Add(tool.Name);
return toolNames;
}
private void ProcessChanged(string selectedProcess) {
if (!selectedProcess.Equals(mrb.Process))
mrb.Tool = "";
mrb.Process = selectedProcess;
StateHasChanged();
}
private void DepartmentChanged(string selectedDepartment) {
if (!selectedDepartment.Equals(mrb.Department))
mrb.Process = "";
mrb.Department = selectedDepartment;
StateHasChanged();
}
}