using System.Net.Http.Headers; using System.Text; using System.Text.Json; using MesaFabApproval.Shared.Models; using MesaFabApproval.Shared.Utilities; using Microsoft.AspNetCore.Components.Forms; using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.Caching.Memory; using MudBlazor; namespace MesaFabApproval.Client.Services; public interface IMRBService { Task> GetAllMRBs(bool bypassCache); Task GetMRBById(int id, bool bypassCache = false); Task GetMRBByTitle(string title, bool bypassCache); Task CreateNewMRB(MRB mrb); Task RecallMRB(MRB mrb, User recallUser); Task DeleteMRB(int mrbNumber); Task UpdateMRB(MRB mrb); Task SubmitForApproval(MRB mrb); Task GenerateActionTasks(MRB mrb, MRBAction action); Task CreateMRBAction(MRBAction mrbAction); Task> GetMRBActionsForMRB(int mrbNumber, bool bypassCache); Task UpdateMRBAction(MRBAction mrbAction); Task DeleteMRBAction(MRBAction mrbAction); Task UploadAttachments(IEnumerable files, int mrbNumber); Task UploadActionAttachments(IEnumerable files, int actionId); Task> GetAllAttachmentsForMRB(int mrbNumber, bool bypassCache); Task> GetAllActionAttachmentsForMRB(int mrbNumber, bool bypassCache); Task DeleteAttachment(MRBAttachment attachment); Task NotifyNewApprovals(MRB mrb); Task NotifyApprovers(MRBNotification notification); Task NotifyOriginator(MRBNotification notification); Task NotifyQAPreApprover(MRBNotification notification); Task NumberIsValid(int number); } public class MRBService : IMRBService { private readonly IMemoryCache _cache; private readonly IHttpClientFactory _httpClientFactory; private readonly ISnackbar _snackbar; private readonly IUserService _userService; private readonly IApprovalService _approvalService; public MRBService(IMemoryCache cache, IHttpClientFactory httpClientFactory, ISnackbar snackbar, IUserService userService, IApprovalService approvalService) { _cache = cache ?? throw new ArgumentNullException("IMemoryCache not injected"); _httpClientFactory = httpClientFactory ?? throw new ArgumentNullException("IHttpClientFactory not injected"); _snackbar = snackbar ?? throw new ArgumentNullException("ISnackbar not injected"); _userService = userService ?? throw new ArgumentNullException("IUserService not injected"); _approvalService = approvalService ?? throw new ArgumentNullException("IApprovalService not injected"); } public async Task CreateNewMRB(MRB mrb) { if (mrb is null) throw new ArgumentNullException("MRB cannot be null"); HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Post, "mrb/new"); requestMessage.Content = new StringContent(JsonSerializer.Serialize(mrb), Encoding.UTF8, "application/json"); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (!responseMessage.IsSuccessStatusCode) { throw new Exception($"Unable to generate new MRB, because {responseMessage.ReasonPhrase}"); } mrb = await GetMRBByTitle(mrb.Title, true); _cache.Set($"mrb{mrb.MRBNumber}", mrb, DateTimeOffset.Now.AddHours(1)); _cache.Set($"mrb{mrb.Title}", mrb, DateTimeOffset.Now.AddHours(1)); IEnumerable? allMrbs = _cache.Get>("allMrbs"); if (allMrbs is not null) { List mrbList = allMrbs.ToList(); mrbList.Add(mrb); _cache.Set("allMrbs", mrbList); } } public async Task RecallMRB(MRB mrb, User recallUser) { if (mrb is null) throw new ArgumentNullException("MRB cannot be null"); if (mrb.StageNo < 1) throw new ArgumentException("MRB already in Draft stage"); if (mrb.StageNo >= 4) throw new Exception("you cannot recall a completed MRB"); mrb.StageNo = 0; mrb.SubmittedDate = DateTimeUtilities.MIN_DT; mrb.ApprovalDate = DateTimeUtilities.MAX_DT; mrb.CloseDate = DateTimeUtilities.MAX_DT; await UpdateMRB(mrb); IEnumerable approvals = await _approvalService.GetApprovalsForIssueId(mrb.MRBNumber, false); foreach (Approval approval in approvals) { if (approval.CompletedDate >= DateTimeUtilities.MAX_DT) { string comment = $"Recalled by {recallUser.GetFullName()}."; approval.Comments = comment; approval.CompletedDate = DateTime.Now; approval.ItemStatus = -1; await _approvalService.UpdateApproval(approval); } } string message = $"MRB# {mrb.MRBNumber} [{mrb.Title}] has been recalled by {recallUser.GetFullName()}."; MRBNotification notification = new() { Message = message, MRB = mrb }; await NotifyApprovers(notification); } public async Task DeleteMRB(int mrbNumber) { if (mrbNumber <= 0) throw new ArgumentException($"{mrbNumber} is not a valid MRB#"); HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Delete, $"mrb/delete?mrbNumber={mrbNumber}"); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (!responseMessage.IsSuccessStatusCode) { throw new Exception($"Unable to delete MRB# {mrbNumber}, because {responseMessage.ReasonPhrase}"); } IEnumerable allMRBs = await GetAllMRBs(true); _cache.Set("allMrbs", allMRBs); } public async Task> GetAllMRBs(bool bypassCache) { try { IEnumerable? allMRBs = null; if (!bypassCache) allMRBs = _cache.Get>("allMrbs"); if (allMRBs is null) { HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Get, $"mrb/all?bypassCache={bypassCache}"); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (responseMessage.IsSuccessStatusCode) { string responseContent = await responseMessage.Content.ReadAsStringAsync(); JsonSerializerOptions jsonSerializerOptions = new() { PropertyNameCaseInsensitive = true }; allMRBs = JsonSerializer.Deserialize>(responseContent, jsonSerializerOptions) ?? throw new Exception("Unable to parse MRBs from API response"); _cache.Set($"allMrbs", allMRBs, DateTimeOffset.Now.AddMinutes(15)); } else { throw new Exception($"Unable to get all MRBs, because {responseMessage.ReasonPhrase}"); } } return allMRBs; } catch (Exception) { throw; } } public async Task NumberIsValid(int number) { try { if (number <= 0) return false; HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Get, $"mrb/numberIsValid?number={number}"); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (responseMessage.IsSuccessStatusCode) { string responseContent = await responseMessage.Content.ReadAsStringAsync(); JsonSerializerOptions jsonSerializerOptions = new() { PropertyNameCaseInsensitive = true }; bool isValid = JsonSerializer.Deserialize(responseContent, jsonSerializerOptions); return isValid; } else { throw new Exception(responseMessage.ReasonPhrase); } } catch (Exception ex) { throw new Exception($"Unable to determine if {number} is a valid MRB#, because {ex.Message}"); } } public async Task GetMRBById(int id, bool bypassCache=false) { if (id <= 0) throw new ArgumentException($"Invalid MRB number: {id}"); MRB? mrb = null; if (!bypassCache) mrb = _cache.Get($"mrb{id}"); if (mrb is null && !bypassCache) mrb = _cache.Get>("allMrbs")?.FirstOrDefault(m => m.MRBNumber == id); if (mrb is null) { HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Get, $"mrb/getById?id={id}&bypassCache={bypassCache}"); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (responseMessage.IsSuccessStatusCode) { string responseContent = await responseMessage.Content.ReadAsStringAsync(); JsonSerializerOptions jsonSerializerOptions = new() { PropertyNameCaseInsensitive = true }; mrb = JsonSerializer.Deserialize(responseContent, jsonSerializerOptions) ?? throw new Exception("Unable to parse MRB from API response"); _cache.Set($"mrb{mrb.MRBNumber}", mrb, DateTimeOffset.Now.AddHours(1)); } else { throw new Exception($"Unable to get MRB by Id, because {responseMessage.ReasonPhrase}"); } } return mrb; } public async Task GetMRBByTitle(string title, bool bypassCache) { if (string.IsNullOrWhiteSpace(title)) throw new ArgumentException("Title cannot be null or empty"); MRB? mrb = null; if (!bypassCache) mrb = _cache.Get($"mrb{title}"); if (mrb is null && !bypassCache) mrb = _cache.Get>("allMrbs")?.FirstOrDefault(m => m.Title.Equals(title)); if (mrb is null) { HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Get, $"mrb/getByTitle?title={title}&bypassCache={bypassCache}"); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (responseMessage.IsSuccessStatusCode) { string responseContent = await responseMessage.Content.ReadAsStringAsync(); JsonSerializerOptions jsonSerializerOptions = new() { PropertyNameCaseInsensitive = true }; mrb = JsonSerializer.Deserialize(responseContent, jsonSerializerOptions) ?? throw new Exception("Unable to parse MRB from API response"); _cache.Set($"mrb{mrb.Title}", mrb, DateTimeOffset.Now.AddHours(1)); } else { throw new Exception($"Unable to get MRB by title, because {responseMessage.ReasonPhrase}"); } } return mrb; } public async Task UpdateMRB(MRB mrb) { if (mrb is null) throw new ArgumentNullException("MRB cannot be null"); HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Put, $"mrb"); requestMessage.Content = new StringContent(JsonSerializer.Serialize(mrb), Encoding.UTF8, "application/json"); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (!responseMessage.IsSuccessStatusCode) { throw new Exception($"Unable to update MRB, because {responseMessage.ReasonPhrase}"); } _cache.Set($"mrb{mrb.MRBNumber}", mrb, DateTimeOffset.Now.AddHours(1)); _cache.Set($"mrb{mrb.Title}", mrb, DateTimeOffset.Now.AddHours(1)); IEnumerable? allMrbs = _cache.Get>("allMrbs"); if (allMrbs is not null) { List mrbList = allMrbs.ToList(); mrbList.RemoveAll(m => m.MRBNumber == mrb.MRBNumber); mrbList.Add(mrb); _cache.Set("allMrbs", mrbList); } } public async Task CreateMRBAction(MRBAction mrbAction) { if (mrbAction is null) throw new ArgumentNullException("MRB action cannot be null"); HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Post, "mrbAction"); requestMessage.Content = new StringContent(JsonSerializer.Serialize(mrbAction), Encoding.UTF8, "application/json"); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (!responseMessage.IsSuccessStatusCode) throw new Exception($"Unable to create new MRB action, because {responseMessage.ReasonPhrase}"); await GetMRBActionsForMRB(mrbAction.MRBNumber, true); } public async Task> GetMRBActionsForMRB(int mrbNumber, bool bypassCache) { if (mrbNumber <= 0) throw new ArgumentException($"{mrbNumber} is not a valid MRB#"); IEnumerable? mrbActions = null; if (!bypassCache) mrbActions = _cache.Get>($"mrbActions{mrbNumber}"); if (mrbActions is null) { HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Get, $"mrbAction?mrbNumber={mrbNumber}&bypassCache={bypassCache}"); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (responseMessage.IsSuccessStatusCode) { string responseContent = await responseMessage.Content.ReadAsStringAsync(); JsonSerializerOptions jsonSerializerOptions = new() { PropertyNameCaseInsensitive = true }; mrbActions = JsonSerializer.Deserialize>(responseContent, jsonSerializerOptions) ?? new List(); if (mrbActions.Count() > 0) _cache.Set($"mrbActions{mrbNumber}", mrbActions, DateTimeOffset.Now.AddMinutes(5)); } else { throw new Exception($"Unable to get MRB {mrbNumber} actions, because {responseMessage.ReasonPhrase}"); } } return mrbActions; } public async Task UpdateMRBAction(MRBAction mrbAction) { if (mrbAction is null) throw new ArgumentNullException("MRB action cannot be null"); HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Put, $"mrbAction"); requestMessage.Content = new StringContent(JsonSerializer.Serialize(mrbAction), Encoding.UTF8, "application/json"); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (!responseMessage.IsSuccessStatusCode) { throw new Exception($"Unable to update MRB action, because {responseMessage.ReasonPhrase}"); } IEnumerable? mrbActions = _cache.Get>($"mrbActions{mrbAction.MRBNumber}"); if (mrbActions is not null) { List mrbActionList = mrbActions.ToList(); mrbActionList.RemoveAll(a => a.ActionID == mrbAction.ActionID); mrbActionList.Add(mrbAction); _cache.Set($"mrbActions{mrbAction.MRBNumber}", mrbActionList, DateTimeOffset.Now.AddMinutes(5)); } } public async Task DeleteMRBAction(MRBAction mrbAction) { if (mrbAction is null) throw new ArgumentNullException("MRB action cannot be null"); if (mrbAction.ActionID <= 0) throw new ArgumentException($"{mrbAction.ActionID} is not a valid MRBActionID"); if (mrbAction.MRBNumber <= 0) throw new ArgumentException($"{mrbAction.MRBNumber} is not a valid MRBNumber"); HttpClient httpClient = _httpClientFactory.CreateClient("API"); string route = $"mrbAction?mrbActionID={mrbAction.ActionID}&mrbNumber={mrbAction.MRBNumber}"; HttpRequestMessage requestMessage = new(HttpMethod.Delete, route); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (!responseMessage.IsSuccessStatusCode) throw new Exception($"Unable to delete MRB action {mrbAction.ActionID}"); IEnumerable? mrbActions = _cache.Get>($"mrbActions{mrbAction.MRBNumber}"); if (mrbActions is not null) { List mrbActionList = mrbActions.ToList(); mrbActionList.RemoveAll(a => a.ActionID == mrbAction.ActionID); _cache.Set($"mrbActions{mrbAction.MRBNumber}", mrbActionList, DateTimeOffset.Now.AddMinutes(5)); } } public async Task UploadAttachments(IEnumerable files, int mrbNumber) { if (files is null) throw new ArgumentNullException("Files cannot be null"); if (files.Count() <= 0) throw new ArgumentException("Files cannot be empty"); if (mrbNumber <= 0) throw new ArgumentException($"{mrbNumber} is not a valid MRB number"); HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Post, $"mrb/attach?mrbNumber={mrbNumber}"); using MultipartFormDataContent content = new MultipartFormDataContent(); foreach (IBrowserFile file in files) { try { long maxFileSize = 1024L * 1024L * 1024L * 2L; StreamContent fileContent = new StreamContent(file.OpenReadStream(maxFileSize)); FileExtensionContentTypeProvider contentTypeProvider = new FileExtensionContentTypeProvider(); const string defaultContentType = "application/octet-stream"; if (!contentTypeProvider.TryGetContentType(file.Name, out string? contentType)) { contentType = defaultContentType; } fileContent.Headers.ContentType = new MediaTypeHeaderValue(contentType); content.Add(content: fileContent, name: "\"files\"", fileName: file.Name); } catch (Exception ex) { _snackbar.Add($"File {file.Name} not saved, because {ex.Message}"); } } requestMessage.Content = content; HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (!responseMessage.IsSuccessStatusCode) throw new Exception($"Unable to save attachments, because {responseMessage.ReasonPhrase}"); string responseContent = await responseMessage.Content.ReadAsStringAsync(); JsonSerializerOptions jsonSerializerOptions = new() { PropertyNameCaseInsensitive = true }; IEnumerable results = JsonSerializer.Deserialize>(responseContent, jsonSerializerOptions) ?? new List(); foreach (UploadResult result in results) { if (result.UploadSuccessful) { _snackbar.Add($"{result.FileName} successfully uploaded", Severity.Success); } else { _snackbar.Add($"{result.FileName} not uploaded, because {result.Error}", Severity.Error); } } await GetAllAttachmentsForMRB(mrbNumber, true); } public async Task UploadActionAttachments(IEnumerable files, int actionId) { if (files is null) throw new ArgumentNullException("Files cannot be null"); if (files.Count() <= 0) throw new ArgumentException("Files cannot be empty"); if (actionId <= 0) throw new ArgumentException($"{actionId} is not a valid MRB action ID"); HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Post, $"mrb/action/attach?actionId={actionId}"); using MultipartFormDataContent content = new MultipartFormDataContent(); foreach (IBrowserFile file in files) { try { long maxFileSize = 1024L * 1024L * 1024L * 2L; StreamContent fileContent = new StreamContent(file.OpenReadStream(maxFileSize)); FileExtensionContentTypeProvider contentTypeProvider = new FileExtensionContentTypeProvider(); const string defaultContentType = "application/octet-stream"; if (!contentTypeProvider.TryGetContentType(file.Name, out string? contentType)) { contentType = defaultContentType; } fileContent.Headers.ContentType = new MediaTypeHeaderValue(contentType); content.Add(content: fileContent, name: "\"files\"", fileName: file.Name); } catch (Exception ex) { _snackbar.Add($"File {file.Name} not saved, because {ex.Message}"); } } requestMessage.Content = content; HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (!responseMessage.IsSuccessStatusCode) throw new Exception($"Unable to save action attachments, because {responseMessage.ReasonPhrase}"); string responseContent = await responseMessage.Content.ReadAsStringAsync(); JsonSerializerOptions jsonSerializerOptions = new() { PropertyNameCaseInsensitive = true }; IEnumerable results = JsonSerializer.Deserialize>(responseContent, jsonSerializerOptions) ?? new List(); foreach (UploadResult result in results) { if (result.UploadSuccessful) { _snackbar.Add($"{result.FileName} successfully uploaded", Severity.Success); } else { _snackbar.Add($"{result.FileName} not uploaded, because {result.Error}", Severity.Error); } } await GetAllAttachmentsForMRB(actionId, true); } public async Task> GetAllAttachmentsForMRB(int mrbNumber, bool bypassCache) { if (mrbNumber <= 0) throw new ArgumentException($"{mrbNumber} is not a valid MRB#"); IEnumerable? mrbAttachments = null; if (!bypassCache) mrbAttachments = _cache.Get>($"mrbAttachments{mrbNumber}"); if (mrbAttachments is null) { HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Get, $"mrb/attachments?mrbNumber={mrbNumber}&bypassCache={bypassCache}"); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (responseMessage.IsSuccessStatusCode) { string responseContent = await responseMessage.Content.ReadAsStringAsync(); JsonSerializerOptions jsonSerializerOptions = new() { PropertyNameCaseInsensitive = true }; mrbAttachments = JsonSerializer.Deserialize>(responseContent, jsonSerializerOptions) ?? new List(); if (mrbAttachments.Count() > 0) _cache.Set($"mrbAttachments{mrbNumber}", mrbAttachments, DateTimeOffset.Now.AddMinutes(5)); } else { throw new Exception($"Unable to get MRB {mrbNumber} attachments, because {responseMessage.ReasonPhrase}"); } } return mrbAttachments; } public async Task> GetAllActionAttachmentsForMRB(int mrbNumber, bool bypassCache) { if (mrbNumber <= 0) throw new ArgumentException($"{mrbNumber} is not a valid MRB#"); IEnumerable? actionAttachments = null; if (!bypassCache) actionAttachments = _cache.Get>($"mrbActionAttachments{mrbNumber}"); if (actionAttachments is null) { HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Get, $"mrb/action/attachments?mrbNumber={mrbNumber}&bypassCache={bypassCache}"); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (responseMessage.IsSuccessStatusCode) { string responseContent = await responseMessage.Content.ReadAsStringAsync(); JsonSerializerOptions jsonSerializerOptions = new() { PropertyNameCaseInsensitive = true }; actionAttachments = JsonSerializer.Deserialize>(responseContent, jsonSerializerOptions) ?? new List(); if (actionAttachments.Count() > 0) _cache.Set($"mrbActionAttachments{mrbNumber}", actionAttachments, DateTimeOffset.Now.AddMinutes(5)); } else { throw new Exception($"Unable to get MRB {mrbNumber} action attachments, because {responseMessage.ReasonPhrase}"); } } return actionAttachments; } public async Task DeleteAttachment(MRBAttachment attachment) { if (attachment is null) throw new ArgumentNullException("MRB attachment cannot be null"); HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Delete, "mrb/attach"); requestMessage.Content = new StringContent(JsonSerializer.Serialize(attachment), Encoding.UTF8, "application/json"); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (!responseMessage.IsSuccessStatusCode) throw new Exception($"Unable to delete MRB attachment"); IEnumerable? mrbAttachments = _cache.Get>($"mrbAttachments{attachment.MRBNumber}"); if (mrbAttachments is not null) { List mrbAttachmentList = mrbAttachments.ToList(); mrbAttachmentList.RemoveAll(a => a.AttachmentID == attachment.AttachmentID); _cache.Set($"mrbAttachments{attachment.MRBNumber}", mrbAttachmentList, DateTimeOffset.Now.AddMinutes(5)); } } public async Task SubmitForApproval(MRB mrb) { if (mrb is null) throw new ArgumentNullException("MRB cannot be null"); string roleName = "QA_PRE_APPROVAL"; string subRoleName = "QA_PRE_APPROVAL"; if (mrb.StageNo > 1) { roleName = "MRB Approver"; subRoleName = "MRBApprover"; } int roleId = await _approvalService.GetRoleIdForRoleName(roleName); if (roleId <= 0) throw new Exception($"could not find {roleName} role ID"); IEnumerable subRoles = await _approvalService.GetSubRolesForSubRoleName(subRoleName, roleId); foreach (SubRole subRole in subRoles) { IEnumerable members = await _approvalService.GetApprovalGroupMembers(subRole.SubRoleID); foreach (User member in members) { Approval approval = new() { IssueID = mrb.MRBNumber, RoleName = roleName, SubRole = subRole.SubRoleName, UserID = member.UserID, SubRoleID = subRole.SubRoleID, AssignedDate = DateTime.Now, Step = mrb.StageNo }; await _approvalService.CreateApproval(approval); } } } public async Task GenerateActionTasks(MRB mrb, MRBAction action) { if (mrb is null) throw new ArgumentNullException("MRB cannot be null"); if (action is null) throw new ArgumentNullException("MRBAction cannot be null"); string roleName = "MRB Actions"; string subRoleName = "MRBActions"; int roleId = await _approvalService.GetRoleIdForRoleName(roleName); if (roleId <= 0) throw new Exception($"could not find {roleName} role ID"); IEnumerable subRoles = await _approvalService.GetSubRolesForSubRoleName(subRoleName, roleId); foreach (SubRole subRole in subRoles) { IEnumerable members = await _approvalService.GetApprovalGroupMembers(subRole.SubRoleID); foreach (User member in members) { Approval approval = new() { IssueID = action.MRBNumber, RoleName = roleName, SubRole = subRole.SubRoleName, UserID = member.UserID, SubRoleID = subRole.SubRoleID, AssignedDate = DateTime.Now, Step = mrb.StageNo, SubRoleCategoryItem = subRole.SubRoleCategoryItem, TaskID = action.ActionID }; await _approvalService.CreateApproval(approval); } } } public async Task NotifyNewApprovals(MRB mrb) { if (mrb is null) throw new ArgumentNullException("MRB cannot be null"); HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Post, $"mrb/notify/new-approvals"); requestMessage.Content = new StringContent(JsonSerializer.Serialize(mrb), Encoding.UTF8, "application/json"); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (!responseMessage.IsSuccessStatusCode) throw new Exception($"Unable to notify new MRB approvers, because {responseMessage.ReasonPhrase}"); } public async Task NotifyApprovers(MRBNotification notification) { if (notification is null) throw new ArgumentNullException("notification cannot be null"); if (notification.MRB is null) throw new ArgumentNullException("MRB cannot be null"); if (string.IsNullOrWhiteSpace(notification.Message)) throw new ArgumentException("message cannot be null or empty"); HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Post, $"mrb/notify/approvers"); requestMessage.Content = new StringContent(JsonSerializer.Serialize(notification), Encoding.UTF8, "application/json"); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (!responseMessage.IsSuccessStatusCode) throw new Exception($"Unable to notify MRB approvers, because {responseMessage.ReasonPhrase}"); } public async Task NotifyOriginator(MRBNotification notification) { if (notification is null) throw new ArgumentNullException("notification cannot be null"); if (notification.MRB is null) throw new ArgumentNullException("MRB cannot be null"); if (string.IsNullOrWhiteSpace(notification.Message)) throw new ArgumentException("message cannot be null or empty"); HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Post, $"mrb/notify/originator"); requestMessage.Content = new StringContent(JsonSerializer.Serialize(notification), Encoding.UTF8, "application/json"); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (!responseMessage.IsSuccessStatusCode) throw new Exception($"Unable to notify MRB originator, because {responseMessage.ReasonPhrase}"); } public async Task NotifyQAPreApprover(MRBNotification notification) { if (notification is null) throw new ArgumentNullException("notification cannot be null"); if (notification.MRB is null) throw new ArgumentNullException("MRB cannot be null"); if (string.IsNullOrWhiteSpace(notification.Message)) throw new ArgumentException("message cannot be null or empty"); HttpClient httpClient = _httpClientFactory.CreateClient("API"); HttpRequestMessage requestMessage = new(HttpMethod.Post, $"mrb/notify/qa-pre-approver"); requestMessage.Content = new StringContent(JsonSerializer.Serialize(notification), Encoding.UTF8, "application/json"); HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage); if (!responseMessage.IsSuccessStatusCode) throw new Exception($"Unable to notify QA pre approver, because {responseMessage.ReasonPhrase}"); } }