1736 lines
76 KiB
Plaintext
1736 lines
76 KiB
Plaintext
@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) {
|
|
<PageTitle>MRB @mrbNumber</PageTitle>
|
|
|
|
<MudPaper Class="p-2 m-2 d-flex flex-row justify-content-between">
|
|
<MudIconButton Icon="@Icons.Material.Filled.ChevronLeft"
|
|
Variant="Variant.Outlined"
|
|
Color="Color.Dark"
|
|
OnClick="@ReturnToAllMrbs"
|
|
Size="Size.Large" />
|
|
<MudText Typo="Typo.h3" Align="Align.Center">MRB @mrbNumber</MudText>
|
|
<MudPaper Height="100%" Width="0.1%" Square="true" />
|
|
</MudPaper>
|
|
}
|
|
|
|
@if (mrb is not null) {
|
|
<MudTimeline Class="mt-2 pt-2" TimelineOrientation="TimelineOrientation.Horizontal"
|
|
TimelinePosition="TimelinePosition.Bottom">
|
|
@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];
|
|
|
|
<MudTimelineItem Color="@color" Variant="Variant.Filled">
|
|
<MudText Align="Align.Center" Color="@color">@stageName</MudText>
|
|
</MudTimelineItem>
|
|
}
|
|
</MudTimeline>
|
|
|
|
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)) {
|
|
<MudPaper Outlined="true"
|
|
Class="p-2 m-2 d-flex flex-wrap gap-3 justify-content-center align-content-center"
|
|
Elevation="10">
|
|
@if (!mrbIsSubmitted && !string.IsNullOrWhiteSpace(mrb.Title)) {
|
|
<MudButton Variant="Variant.Filled"
|
|
Color="Color.Tertiary"
|
|
Disabled="@saveInProcess"
|
|
OnClick=SaveMRB>
|
|
@if (saveInProcess) {
|
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
|
<MudText>Processing</MudText>
|
|
} else {
|
|
<MudText>Save</MudText>
|
|
}
|
|
</MudButton>
|
|
}
|
|
@if (!mrbIsSubmitted && mrbNumberIsValid && (userIsOriginator || userIsAdmin)) {
|
|
<MudButton Variant="Variant.Filled"
|
|
Color="Color.Secondary"
|
|
Disabled="@deleteInProcess"
|
|
OnClick=DeleteMRB>
|
|
@if (deleteInProcess) {
|
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
|
<MudText>Processing</MudText>
|
|
} else {
|
|
<MudText>Delete</MudText>
|
|
}
|
|
</MudButton>
|
|
}
|
|
@if (!mrbIsSubmitted && mrbReadyToSubmit && (userIsOriginator || userIsAdmin)) {
|
|
<MudButton Variant="Variant.Filled"
|
|
Color="Color.Tertiary"
|
|
Disabled="@submitInProcess"
|
|
OnClick=SubmitMRBForApproval>
|
|
@if (submitInProcess) {
|
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
|
<MudText>Processing</MudText>
|
|
} else {
|
|
<MudText>Submit for Approval</MudText>
|
|
}
|
|
</MudButton>
|
|
}
|
|
@if (mrbIsSubmitted && userIsApprover && approvalsArePending) {
|
|
<MudButton Variant="Variant.Filled"
|
|
Color="Color.Tertiary"
|
|
Disabled="@approvalInProcess"
|
|
OnClick=ApproveMRB>
|
|
@if (approvalInProcess) {
|
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
|
<MudText>Processing</MudText>
|
|
} else {
|
|
<MudText>Approve</MudText>
|
|
}
|
|
</MudButton>
|
|
<MudButton Variant="Variant.Filled"
|
|
Color="Color.Secondary"
|
|
Disabled="@denialInProcess"
|
|
OnClick=DenyMRB>
|
|
@if (denialInProcess) {
|
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
|
<MudText>Processing</MudText>
|
|
} else {
|
|
<MudText>Deny</MudText>
|
|
}
|
|
</MudButton>
|
|
}
|
|
@if ((userIsOriginator || userIsAdmin) && mrb.StageNo > 0 && mrb.StageNo < 4) {
|
|
<MudButton Variant="Variant.Filled"
|
|
Color="Color.Tertiary"
|
|
Disabled="@recallInProcess"
|
|
OnClick=RecallMRB>
|
|
@if (recallInProcess) {
|
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
|
<MudText>Processing</MudText>
|
|
} else {
|
|
<MudText>Recall</MudText>
|
|
}
|
|
</MudButton>
|
|
}
|
|
</MudPaper>
|
|
}
|
|
|
|
@if (!mrbIsSubmitted && GetIncompleteFields().Count() > 0) {
|
|
IEnumerable<string> incompleteFields = GetIncompleteFields();
|
|
StringBuilder errorBuilder = new();
|
|
errorBuilder.Append($"Incomplete fields: {incompleteFields.First()}");
|
|
for (int i = 1; i < incompleteFields.Count(); i++) {
|
|
errorBuilder.Append($", {incompleteFields.ElementAt(i)}");
|
|
}
|
|
|
|
<MudPaper Outlined Class="p-2 m-2">
|
|
<MudText Align="Align.Center" Color="Color.Secondary" Typo="Typo.h6">
|
|
@errorBuilder.ToString()
|
|
</MudText>
|
|
</MudPaper>
|
|
}
|
|
|
|
<MudPaper Outlined="true"
|
|
Class="p-2 m-2 d-flex flex-wrap gap-3 justify-content-center align-content-start"
|
|
Elevation="10">
|
|
<MudTextField @bind-Value=mrb.MRBNumber
|
|
Text="@mrb.MRBNumber.ToString()"
|
|
T="int"
|
|
Disabled="true"
|
|
Label="MRB#"
|
|
Required
|
|
Variant="Variant.Outlined" />
|
|
<MudTextField @bind-Value=mrb.Title
|
|
Text="@mrb.Title"
|
|
Disabled="@(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)"
|
|
T="string"
|
|
AutoGrow
|
|
AutoFocus
|
|
Clearable
|
|
Required
|
|
Variant="Variant.Outlined"
|
|
Label="Title" />
|
|
<MudTextField Disabled="@(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)"
|
|
@bind-Value=mrb.IssueDescription
|
|
Text="@mrb.IssueDescription"
|
|
AutoGrow
|
|
Required
|
|
Clearable
|
|
Variant="Variant.Outlined"
|
|
Label="Description" />
|
|
<MudTextField Disabled="true"
|
|
T="string"
|
|
Value="@DateTimeUtilities.GetDateAsStringMinDefault(mrb.SubmittedDate)"
|
|
Label="Submit Date"
|
|
Variant="Variant.Outlined" />
|
|
<MudTextField Disabled="true"
|
|
Label="Approval Date"
|
|
Variant="Variant.Outlined"
|
|
Value="@DateTimeUtilities.GetDateAsStringMaxDefault(mrb.ApprovalDate)"
|
|
T="string" />
|
|
<MudTextField Disabled="true"
|
|
Label="Closed Date"
|
|
Variant="Variant.Outlined"
|
|
Value="@DateTimeUtilities.GetDateAsStringMaxDefault(mrb.CloseDate)"
|
|
T="string" />
|
|
@if (mrb is not null && mrb.CancelDate < DateTimeUtilities.MAX_DT) {
|
|
<MudTextField Disabled="true"
|
|
Label="Canceled Date"
|
|
Variant="Variant.Outlined"
|
|
Value="@DateTimeUtilities.GetDateAsStringMaxDefault(mrb.CancelDate)"
|
|
T="string" />
|
|
}
|
|
|
|
<MudSelect T="string"
|
|
Label="Originator"
|
|
Variant="Variant.Outlined"
|
|
Required
|
|
Clearable
|
|
AnchorOrigin="Origin.BottomCenter"
|
|
Disabled=@(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)
|
|
@bind-Value=mrb.OriginatorName
|
|
Text="@mrb.OriginatorName">
|
|
@foreach (User user in allActiveUsers.OrderBy(u => u.LastName)) {
|
|
<MudSelectItem T="string" Value="@($"{user.FirstName} {user.LastName}")" />
|
|
}
|
|
</MudSelect>
|
|
<MudSelect T="string"
|
|
Label="Category"
|
|
Variant="Variant.Outlined"
|
|
Required
|
|
Immediate
|
|
Clearable
|
|
AnchorOrigin="Origin.BottomCenter"
|
|
Disabled=@(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)
|
|
@bind-Value=mrb.Category
|
|
Text="@mrb.Category">
|
|
<MudSelectItem Value="@("Material Containment")" />
|
|
<MudSelectItem Value="@("Material Release")" />
|
|
<MudSelectItem Value="@("Material Transfer")" />
|
|
</MudSelect>
|
|
<MudSelect T="string"
|
|
Label="Department"
|
|
Variant="Variant.Outlined"
|
|
Required
|
|
Clearable
|
|
AnchorOrigin="Origin.BottomCenter"
|
|
Disabled=@(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)
|
|
ValueChanged="@DepartmentChanged"
|
|
Text="@mrb.Department">
|
|
<MudSelectItem Value="@("Production")" />
|
|
<MudSelectItem Value="@("Engineering")" />
|
|
<MudSelectItem Value="@("Materials")" />
|
|
<MudSelectItem Value="@("Facilities")" />
|
|
<MudSelectItem Value="@("Maintenance")" />
|
|
<MudSelectItem Value="@("Quality")" />
|
|
</MudSelect>
|
|
<MudSelect T="string"
|
|
Label="Process"
|
|
Variant="Variant.Outlined"
|
|
Required
|
|
Clearable
|
|
AnchorOrigin="Origin.BottomCenter"
|
|
Disabled=@(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)
|
|
ValueChanged="@ProcessChanged"
|
|
Text="@mrb.Process">
|
|
@if (mrb.Department.Equals("Production")) {
|
|
foreach (Process process in Process.ProductionProcesses) {
|
|
<MudSelectItem Value="@process.Name" />
|
|
}
|
|
} else if (mrb.Department.Equals("Engineering")) {
|
|
foreach (Process process in Process.EngineeringProcesses) {
|
|
<MudSelectItem Value="@process.Name" />
|
|
}
|
|
} else if (mrb.Department.Equals("Materials")) {
|
|
foreach (Process process in Process.MaterialsProcesses) {
|
|
<MudSelectItem Value="@process.Name" />
|
|
}
|
|
} else if (mrb.Department.Equals("Facilities")) {
|
|
foreach (Process process in Process.FacilitiesProcesses) {
|
|
<MudSelectItem Value="@process.Name" />
|
|
}
|
|
} else if (mrb.Department.Equals("Maintenance")) {
|
|
foreach (Process process in Process.MaintenanceProcesses) {
|
|
<MudSelectItem Value="@process.Name" />
|
|
}
|
|
} else if (mrb.Department.Equals("Quality")) {
|
|
foreach (Process process in Process.QualityProcesses) {
|
|
<MudSelectItem Value="@process.Name" />
|
|
}
|
|
}
|
|
</MudSelect>
|
|
@if (mrb.Process.Equals("Reactor") ||
|
|
mrb.Process.Equals("Metrology") ||
|
|
mrb.Process.Equals("Cleans") ||
|
|
mrb.Process.Equals("Packaging") ||
|
|
mrb.Process.Equals("Final QA")) {
|
|
<MudSelect T="string"
|
|
Label="Tool"
|
|
Clearable
|
|
Variant="Variant.Outlined"
|
|
AnchorOrigin="Origin.BottomCenter"
|
|
Disabled=@(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)
|
|
Text="@mrb.Tool"
|
|
@bind-Value=mrb.Tool
|
|
>
|
|
<MudSelectItem Value="@string.Empty" />
|
|
@if (mrb.Process.Equals("Reactor")) {
|
|
@foreach (Tool tool in Tool.ReactorTools) {
|
|
<MudSelectItem Value="@tool.Name" />
|
|
}
|
|
}
|
|
@if (mrb.Process.Equals("Metrology")) {
|
|
@foreach (Tool tool in Tool.MetrologyTools) {
|
|
<MudSelectItem Value="@tool.Name" />
|
|
}
|
|
}
|
|
@if (mrb.Process.Equals("Cleans")) {
|
|
@foreach (Tool tool in Tool.CleansTools) {
|
|
<MudSelectItem Value="@tool.Name" />
|
|
}
|
|
}
|
|
@if (mrb.Process.Equals("Packaging")) {
|
|
@foreach (Tool tool in Tool.PackagingTools) {
|
|
<MudSelectItem Value="@tool.Name" />
|
|
}
|
|
}
|
|
@if (mrb.Process.Equals("Final QA")) {
|
|
@foreach (Tool tool in Tool.FqaTools) {
|
|
<MudSelectItem Value="@tool.Name" />
|
|
}
|
|
}
|
|
</MudSelect>
|
|
}
|
|
|
|
<MudTextField Disabled="true"
|
|
@bind-Value=mrb.NumberOfLotsAffected
|
|
Text="@mrb.NumberOfLotsAffected.ToString()"
|
|
Variant="Variant.Outlined"
|
|
Clearable
|
|
Immediate
|
|
Label="Total Quantity" />
|
|
<MudNumericField @bind-Value=mrb.Val
|
|
Required
|
|
Label="Value"
|
|
Variant="Variant.Outlined"
|
|
Adornment="Adornment.Start"
|
|
AdornmentIcon="@Icons.Material.Filled.AttachMoney"
|
|
AdornmentColor="Color.Success"
|
|
Immediate
|
|
ErrorText="Value must be greater than 0"
|
|
Validation="new Func<double, bool>(v => v > 0)"
|
|
Clearable
|
|
Disabled="@(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)" />
|
|
<MudTextField Disabled="@(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)"
|
|
@bind-Value=mrb.RMANo
|
|
Text="@mrb.RMANo.ToString()"
|
|
Clearable
|
|
Variant="Variant.Outlined"
|
|
Label="RMA#" />
|
|
<MudTextField Disabled="@(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)"
|
|
@bind-Value=mrb.PCRBNo
|
|
@ref=pcrbNoField
|
|
Text="@mrb.PCRBNo"
|
|
Variant="Variant.Outlined"
|
|
Clearable
|
|
Immediate
|
|
AutoGrow
|
|
Validation="@(new Func<string, Task<string>>(PCRBNoIsValid))"
|
|
Label="PCRB#" />
|
|
<MudPaper Outlined="true" Class="p-2">
|
|
<MudCheckBox Disabled="@(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)"
|
|
Color="Color.Tertiary"
|
|
ValueChanged="@(new Func<bool, Task>(SpecsImpactedChanged))"
|
|
Label="Specs Impacted?"
|
|
LabelPosition="LabelPosition.Start" />
|
|
@if (mrb.SpecsImpacted) {
|
|
<MudTextField Disabled="@(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)"
|
|
@bind-Value=mrb.ProcessECNNumber
|
|
@ref=processEcnField
|
|
Required
|
|
Clearable
|
|
Variant="Variant.Outlined"
|
|
InputType="@InputType.Number"
|
|
Validation="@(new Func<int, Task<string>>(ECNNoIsValid))"
|
|
Label="Process ECN#"
|
|
Immediate
|
|
AutoGrow />
|
|
}
|
|
</MudPaper>
|
|
<MudPaper Outlined="true" Class="p-2">
|
|
<MudCheckBox Disabled="@(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)"
|
|
ValueChanged="@(new Func<bool, Task>(CustomerImpactedChanged))"
|
|
Color="Color.Tertiary"
|
|
Label="Customer Impacted?"
|
|
LabelPosition="LabelPosition.Start" />
|
|
@if (mrb.CustomerImpacted) {
|
|
<MudSelect T="string"
|
|
Label="Affected Customer"
|
|
Required
|
|
Clearable
|
|
Variant="Variant.Outlined"
|
|
AnchorOrigin="Origin.BottomCenter"
|
|
Disabled=@(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)
|
|
@bind-Value=mrb.CustomerImpactedName
|
|
Text="@mrb.CustomerImpactedName">
|
|
@foreach (string customer in customerNames) {
|
|
<MudSelectItem Value="@(customer)" />
|
|
}
|
|
</MudSelect>
|
|
}
|
|
</MudPaper>
|
|
</MudPaper>
|
|
}
|
|
|
|
@if (mrb is not null && mrb.MRBNumber > 0) {
|
|
<MudPaper Outlined="true"
|
|
Class="p-2 m-2 d-flex flex-column justify-start">
|
|
<MudText Typo="Typo.h4" Align="Align.Center">Supporting Documents</MudText>
|
|
<MudDivider DividerType="DividerType.Middle" Class="my-2" />
|
|
@if (!(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)) {
|
|
<MudFileUpload T="IReadOnlyList<IBrowserFile>" OnFilesChanged="AddAttachments" Class="centered-upload">
|
|
<ActivatorContent>
|
|
<MudButton Variant="Variant.Filled"
|
|
Color="Color.Tertiary"
|
|
style="margin: auto;"
|
|
Disabled="@attachmentUploadInProcess"
|
|
StartIcon="@Icons.Material.Filled.AttachFile" >
|
|
@if (attachmentUploadInProcess) {
|
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
|
<MudText>Processing</MudText>
|
|
} else {
|
|
<MudText>Upload Document</MudText>
|
|
}
|
|
</MudButton>
|
|
</ActivatorContent>
|
|
</MudFileUpload>
|
|
}
|
|
|
|
@if (mrbAttachments is not null) {
|
|
<MudTable Items="@mrbAttachments"
|
|
Class="m-2"
|
|
Striped="true"
|
|
Filter="new Func<MRBAttachment, bool>(FilterFuncForMRBAttachmentTable)"
|
|
SortLabel="Sort By"
|
|
Hover="true">
|
|
<ToolBarContent>
|
|
<MudSpacer />
|
|
<MudTextField @bind-Value="attachmentSearchString"
|
|
Placeholder="Search"
|
|
Adornment="Adornment.Start"
|
|
AdornmentIcon="@Icons.Material.Filled.Search"
|
|
IconSize="Size.Medium"
|
|
Class="mt-0" />
|
|
</ToolBarContent>
|
|
<HeaderContent>
|
|
<MudTh>
|
|
<MudTableSortLabel SortBy="new Func<MRBAttachment, object>(x=>x.FileName)">
|
|
Name
|
|
</MudTableSortLabel>
|
|
</MudTh>
|
|
<MudTh>
|
|
<MudTableSortLabel InitialDirection="SortDirection.Descending" SortBy="new Func<MRBAttachment,object>(x=>x.UploadDate)">
|
|
Upload Date
|
|
</MudTableSortLabel>
|
|
</MudTh>
|
|
</HeaderContent>
|
|
<RowTemplate>
|
|
<MudTd DataLabel="Name">
|
|
<a href="@(@$"{config["FabApprovalApiBaseUrl"]}/mrb/attachmentFile?path={context.Path}&fileName={context.FileName}")"
|
|
download="@(context.FileName)"
|
|
target="_top">
|
|
@context.FileName
|
|
</a>
|
|
</MudTd>
|
|
<MudTd DataLabel="Upload Date">@context.UploadDate.ToString("yyyy-MM-dd HH:mm")</MudTd>
|
|
@if (mrb is not null && !(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)) {
|
|
<MudTd>
|
|
<MudButton Color="Color.Secondary"
|
|
Variant="Variant.Filled"
|
|
Disabled="@deleteActionInProcess"
|
|
OnClick="@((e) => DeleteAttachment(context))">
|
|
@if (deleteActionInProcess) {
|
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
|
<MudText>Deleting</MudText>
|
|
} else {
|
|
<MudText>Delete</MudText>
|
|
}
|
|
</MudButton>
|
|
</MudTd>
|
|
}
|
|
</RowTemplate>
|
|
</MudTable>
|
|
}
|
|
</MudPaper>
|
|
|
|
<MudPaper Outlined="true"
|
|
Class="p-2 m-2 d-flex flex-column justify-start">
|
|
<MudText Typo="Typo.h4" Align="Align.Center">Actions</MudText>
|
|
<MudDivider DividerType="DividerType.Middle" Class="my-2" />
|
|
@if (!(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)) {
|
|
<MudButton Variant="Variant.Filled"
|
|
Color="Color.Tertiary"
|
|
Class="flex-grow-0"
|
|
Style="max-width: 185px;"
|
|
OnClick="@((e) => CreateNewAction())">
|
|
Create New Action
|
|
</MudButton>
|
|
}
|
|
|
|
@if (mrb.SubmittedDate > DateTimeUtilities.MIN_DT && mrb.StageNo == 3 &&
|
|
(currentUser?.UserID == mrb.OriginatorID || currentUser?.IsAdmin == true)) {
|
|
<MudButton Variant="Variant.Filled"
|
|
Color="Color.Tertiary"
|
|
Class="flex-grow-0"
|
|
Style="max-width: 185px;"
|
|
Disabled="@completeAllActionsInProcess"
|
|
OnClick="@((e) => CompleteAllActions())">
|
|
@if (completeAllActionsInProcess) {
|
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
|
<MudText>Processing</MudText>
|
|
} else {
|
|
<MudText>Complete All Actions</MudText>
|
|
}
|
|
</MudButton>
|
|
}
|
|
|
|
@if (mrbActions is not null) {
|
|
<MudTable Items="@mrbActions"
|
|
Class="m-2"
|
|
Striped="true"
|
|
Filter="new Func<MRBAction, bool>(FilterFuncForMRBActionTable)"
|
|
SortLabel="Sort By"
|
|
Hover="true">
|
|
<ToolBarContent>
|
|
<a href="@(@$"{config["FabApprovalApiBaseUrl"]}/mrb/actions/csvFile?mrbNumber={mrbNumberInt}")"
|
|
download
|
|
target="_top">
|
|
Download as CSV File
|
|
</a>
|
|
<MudSpacer />
|
|
<MudTextField @bind-Value="actionSearchString"
|
|
Placeholder="Search"
|
|
Adornment="Adornment.Start"
|
|
AdornmentIcon="@Icons.Material.Filled.Search"
|
|
IconSize="Size.Medium"
|
|
Class="mt-0" />
|
|
</ToolBarContent>
|
|
<HeaderContent>
|
|
<MudTh>
|
|
<MudTableSortLabel InitialDirection="SortDirection.Ascending" SortBy="new Func<MRBAction,object>(x=>x.Action)">
|
|
Action
|
|
</MudTableSortLabel>
|
|
</MudTh>
|
|
<MudTh>
|
|
<MudTableSortLabel SortBy="new Func<MRBAction,object>(x=>x.Customer)">
|
|
Customer
|
|
</MudTableSortLabel>
|
|
</MudTh>
|
|
<MudTh>
|
|
<MudTableSortLabel SortBy="new Func<MRBAction,object>(x=>x.Quantity)">
|
|
Qty
|
|
</MudTableSortLabel>
|
|
</MudTh>
|
|
<MudTh>
|
|
<MudTableSortLabel SortBy="new Func<MRBAction,object>(x=>x.PartNumber)">
|
|
Part Number
|
|
</MudTableSortLabel>
|
|
</MudTh>
|
|
<MudTh>
|
|
<MudTableSortLabel SortBy="new Func<MRBAction,object>(x=>x.LotNumber)">
|
|
Batch Number / Lot Number
|
|
</MudTableSortLabel>
|
|
</MudTh>
|
|
<MudTh>
|
|
Justification
|
|
</MudTh>
|
|
<MudTh>
|
|
<MudTableSortLabel SortBy="new Func<MRBAction, object>(x=>x.AssignedDate)">
|
|
Assigned Date
|
|
</MudTableSortLabel>
|
|
</MudTh>
|
|
<MudTh>
|
|
<MudTableSortLabel SortBy="new Func<MRBAction, object>(x=>x.CompletedDate)">
|
|
Completed Date
|
|
</MudTableSortLabel>
|
|
</MudTh>
|
|
<MudTh>
|
|
<MudTableSortLabel InitialDirection="SortDirection.Ascending" SortBy="new Func<MRBAction,object>(x=>x.CompletedByUser?.GetFullName() ??
|
|
x.CompletedByUserID.ToString())">
|
|
Completed By
|
|
</MudTableSortLabel>
|
|
</MudTh>
|
|
<MudTh>
|
|
<MudTableSortLabel T="string">
|
|
Comments
|
|
</MudTableSortLabel>
|
|
</MudTh>
|
|
<MudTh>
|
|
Attachments
|
|
</MudTh>
|
|
</HeaderContent>
|
|
<RowTemplate>
|
|
@if (context.Action.ToLower().Equals("convert")) {
|
|
<MudTd DataLabel="Action">@context.Action @context.ConvertFrom to @context.ConvertTo</MudTd>
|
|
} else {
|
|
<MudTd DataLabel="Action">@context.Action</MudTd>
|
|
}
|
|
<MudTd DataLabel="Customer">@context.Customer</MudTd>
|
|
<MudTd DataLabel="Qty">@context.Quantity</MudTd>
|
|
<MudTd DataLabel="Part Number">@context.PartNumber</MudTd>
|
|
<MudTd DataLabel="Batch Number / Lot Number">@context.LotNumber</MudTd>
|
|
<MudTd DataLabel="Justification">@context.Justification</MudTd>
|
|
<MudTd DataLabel="Assigned Date">@DateTimeUtilities.GetDateAsStringMinDefault(context.AssignedDate)</MudTd>
|
|
<MudTd DataLabel="Completed Date">@DateTimeUtilities.GetDateAsStringMaxDefault(context.CompletedDate)</MudTd>
|
|
<MudTd DataLabel="Completed By">@context.CompletedByUser?.GetFullName()</MudTd>
|
|
<MudTd DataLabel="Comments">
|
|
@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) {
|
|
<MudText>@approval.Comments</MudText>
|
|
} else {
|
|
<MudText>@string.Empty</MudText>
|
|
}
|
|
}
|
|
</MudTd>
|
|
<MudTd DataLabel="Attachments">
|
|
@if (mrbActionAttachments.Where(a => a.ActionID == context.ActionID).Count() > 0) {
|
|
IEnumerable<MRBActionAttachment> attachments = mrbActionAttachments.Where(a => a.ActionID == context.ActionID).ToList();
|
|
foreach (MRBActionAttachment attachment in attachments) {
|
|
<MudTooltip Text="@attachment.FileName">
|
|
<MudFab Color="Color.Success"
|
|
StartIcon="@Icons.Material.Filled.AttachFile"
|
|
Size="Size.Small"
|
|
Href="@(@$"{config["FabApprovalApiBaseUrl"]}/mrb/attachmentFile?path={attachment.Path}&fileName={attachment.FileName}")" />
|
|
</MudTooltip>
|
|
}
|
|
}
|
|
</MudTd>
|
|
@if (mrb is not null && !(mrb.SubmittedDate > DateTimeUtilities.MIN_DT)) {
|
|
<MudTd>
|
|
<MudButton Variant="Variant.Filled"
|
|
Color="Color.Tertiary"
|
|
OnClick="@((e) => EditAction(context))">
|
|
Edit
|
|
</MudButton>
|
|
<MudButton Color="Color.Secondary"
|
|
Variant="Variant.Filled"
|
|
Disabled="@deleteActionInProcess"
|
|
OnClick="@((e) => DeleteAction(context))">
|
|
@if (deleteActionInProcess) {
|
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
|
<MudText>Deleting</MudText>
|
|
} else {
|
|
<MudText>Delete</MudText>
|
|
}
|
|
</MudButton>
|
|
</MudTd>
|
|
}
|
|
@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) {
|
|
<MudTd>
|
|
<MudButton Variant="Variant.Filled"
|
|
Color="Color.Tertiary"
|
|
OnClick="@((e) => CompleteAction(context))">
|
|
Mark Complete
|
|
</MudButton>
|
|
</MudTd>
|
|
}
|
|
</RowTemplate>
|
|
<PagerContent>
|
|
<MudTablePager />
|
|
</PagerContent>
|
|
</MudTable>
|
|
}
|
|
</MudPaper>
|
|
|
|
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;
|
|
|
|
<MudPaper Outlined="true"
|
|
Class="p-2 m-2 d-flex flex-column justify-center">
|
|
<MudText Typo="Typo.h4" Align="Align.Center">Approvals</MudText>
|
|
<MudDivider DividerType="DividerType.Middle" Class="my-2" />
|
|
@if (!mrbIsSubmitted && mrbReadyToSubmit && (userIsOriginator || userIsAdmin)) {
|
|
<MudButton Variant="Variant.Filled"
|
|
Color="Color.Tertiary"
|
|
Style="max-width: 185px;"
|
|
Disabled="@submitInProcess"
|
|
OnClick=SubmitMRBForApproval>
|
|
@if (submitInProcess) {
|
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
|
<MudText>Processing</MudText>
|
|
} else {
|
|
<MudText>Submit for Approval</MudText>
|
|
}
|
|
</MudButton>
|
|
}
|
|
|
|
@if (nonTaskApprovals is not null) {
|
|
<MudTable Items="@nonTaskApprovals"
|
|
Class="m-2"
|
|
Striped="true">
|
|
<HeaderContent>
|
|
<MudTh>Role</MudTh>
|
|
<MudTh>Approver Name</MudTh>
|
|
<MudTh>Status</MudTh>
|
|
<MudTh>Assigned Date</MudTh>
|
|
<MudTh>Disposition Date</MudTh>
|
|
<MudTh>Comments</MudTh>
|
|
</HeaderContent>
|
|
<RowTemplate>
|
|
<MudTd DataLabel="Role">@context.SubRoleCategoryItem</MudTd>
|
|
<MudTd DataLabel="Approver Name">@context.User?.GetFullName()</MudTd>
|
|
<MudTd DataLabel="Status">@context.StatusMessage</MudTd>
|
|
<MudTd DataLabel="Assigned Date">@DateTimeUtilities.GetDateAsStringMaxDefault(context.AssignedDate)</MudTd>
|
|
<MudTd DataLabel="Disposition Date">@DateTimeUtilities.GetDateAsStringMaxDefault(context.CompletedDate)</MudTd>
|
|
<MudTd DataLabel="Comments">@context.Comments</MudTd>
|
|
@if (context.ItemStatus == 0 && authStateProvider.CurrentUser is not null && authStateProvider.CurrentUser.IsAdmin) {
|
|
<MudTd>
|
|
<MudButton Variant="Variant.Filled"
|
|
Color="Color.Warning"
|
|
OnClick="@((e) => ReassignApproval(context))">
|
|
Reassign
|
|
</MudButton>
|
|
</MudTd>
|
|
}
|
|
</RowTemplate>
|
|
</MudTable>
|
|
}
|
|
</MudPaper>
|
|
}
|
|
|
|
<MudOverlay Visible=processing DarkBackground="true" AutoClose="false">
|
|
<MudProgressCircular Color="Color.Info" Size="Size.Large" Indeterminate="true" />
|
|
</MudOverlay>
|
|
|
|
@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<User> allActiveUsers = new List<User>();
|
|
private IEnumerable<MRBAction> mrbActions = new List<MRBAction>();
|
|
private IEnumerable<MRBActionAttachment> mrbActionAttachments = new List<MRBActionAttachment>();
|
|
private IEnumerable<MRBAttachment> mrbAttachments = new List<MRBAttachment>();
|
|
private IEnumerable<Approval> mrbApprovals = new List<Approval>();
|
|
private IEnumerable<Approval> nonTaskApprovals = new List<Approval>();
|
|
private IEnumerable<Approval> taskApprovals = new List<Approval>();
|
|
private IEnumerable<string> customerNames = new List<string>();
|
|
private IEnumerable<string> partNumbers = new List<string>();
|
|
private IEnumerable<string> lotNumbers = new List<string>();
|
|
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<int>? processEcnField;
|
|
private bool processEcnIsValid = false;
|
|
private MudTextField<string>? 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<MRBAction>();
|
|
mrbAttachments = new List<MRBAttachment>();
|
|
mrbApprovals = new List<Approval>();
|
|
nonTaskApprovals = new List<Approval>();
|
|
taskApprovals = new List<Approval>();
|
|
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<Comments> parameters = new DialogParameters<Comments> { { x => x.comments, comments } };
|
|
var dialog = dialogService.Show<Comments>($"Approval Comments", parameters);
|
|
|
|
var result = await dialog.Result;
|
|
|
|
if (result.Canceled) throw new Exception("you must provide approval comments");
|
|
|
|
comments = result.Data.ToString();
|
|
|
|
IEnumerable<Approval> 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<Approval> 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<Approval> 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<Comments> parameters = new DialogParameters<Comments> { { x => x.comments, comments } };
|
|
var dialog = dialogService.Show<Comments>($"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<Approval> 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<MRBActionCommentsAndFiles> parameters = new DialogParameters<MRBActionCommentsAndFiles> {
|
|
{ x => x.comments, comments },
|
|
{ x => x.actionId, action.ActionID} };
|
|
var dialog = dialogService.Show<MRBActionCommentsAndFiles>($"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<MRBActionCommentsAndFiles> parameters = new DialogParameters<MRBActionCommentsAndFiles> {
|
|
{ x => x.comments, comments },
|
|
{ x => x.actionId, firstAction.ActionID} };
|
|
var dialog = dialogService.Show<MRBActionCommentsAndFiles>($"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<string> GetIncompleteFields() {
|
|
List<string> 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<Approval> 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<MRBActionForm> parameters = new DialogParameters<MRBActionForm> { { x => x.mrbAction, mrbAction } };
|
|
var dialog = dialogService.Show<MRBActionForm>($"New MRB Action", parameters);
|
|
|
|
var result = await dialog.Result;
|
|
|
|
if (!result.Canceled) {
|
|
if (mrbNumberInt > 0) {
|
|
mrbActions = await mrbService.GetMRBActionsForMRB(mrbNumberInt, true);
|
|
} else {
|
|
List<MRBAction> 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<MRBActionForm> { { x => x.mrbAction, mrbAction } };
|
|
var dialog = dialogService.Show<MRBActionForm>($"MRB Action {mrbAction.ActionID}", parameters);
|
|
|
|
var result = await dialog.Result;
|
|
|
|
if (!result.Canceled) {
|
|
if (mrbNumberInt > 0) {
|
|
mrbActions = await mrbService.GetMRBActionsForMRB(mrbNumberInt, true);
|
|
} else {
|
|
List<MRBAction> 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<MRBAction> 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<IBrowserFile> 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<MRBAttachment> 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<string> PCRBNoIsValid(string id) {
|
|
string? result = await pcrbService.IdIsValid(id);
|
|
if (result is null) pcrbNoIsValid = true;
|
|
else pcrbNoIsValid = false;
|
|
StateHasChanged();
|
|
return result;
|
|
}
|
|
|
|
private async Task<string> 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<MRBApproverSelector> parameters = new DialogParameters<MRBApproverSelector> { { x => x.selectedUser, selectedUser } };
|
|
var dialog = dialogService.Show<MRBApproverSelector>($"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<string> GetPartNumbers() {
|
|
HashSet<string> partNumbers = new();
|
|
foreach (MRBAction action in mrbActions) {
|
|
partNumbers.Add(action.PartNumber);
|
|
}
|
|
return partNumbers;
|
|
}
|
|
|
|
private IEnumerable<string> GetLotNumbers() {
|
|
HashSet<string> lotNumbers = new();
|
|
foreach (MRBAction action in mrbActions) {
|
|
lotNumbers.Add(action.LotNumber);
|
|
}
|
|
return lotNumbers;
|
|
}
|
|
|
|
private async Task<IEnumerable<string>> ToolSearch(string value, CancellationToken token) {
|
|
IEnumerable<Tool> matchingTools =
|
|
Tool.FqaTools.Where(t => t.Name.Contains(value, StringComparison.InvariantCultureIgnoreCase));
|
|
HashSet<string> 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();
|
|
}
|
|
} |