PCRB follow up client side logic
This commit is contained in:
55
MesaFabApproval.API.Test/ApprovalServiceTests.cs
Normal file
55
MesaFabApproval.API.Test/ApprovalServiceTests.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using MesaFabApproval.API.Services;
|
||||||
|
using MesaFabApproval.Shared.Models;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
using Moq;
|
||||||
|
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace MesaFabApproval.API.Test;
|
||||||
|
|
||||||
|
public class ApprovalServiceTests {
|
||||||
|
private readonly Mock<ILogger<ApprovalService>> _loggerMock;
|
||||||
|
private readonly Mock<IMemoryCache> _cacheMock;
|
||||||
|
private readonly Mock<IDalService> _dalServiceMock;
|
||||||
|
private readonly Mock<IUserService> _userServiceMock;
|
||||||
|
private readonly ApprovalService _approvalService;
|
||||||
|
|
||||||
|
public ApprovalServiceTests() {
|
||||||
|
_loggerMock = new Mock<ILogger<ApprovalService>>();
|
||||||
|
_cacheMock = new Mock<IMemoryCache>();
|
||||||
|
_dalServiceMock = new Mock<IDalService>();
|
||||||
|
_userServiceMock = new Mock<IUserService>();
|
||||||
|
_approvalService = new ApprovalService(_loggerMock.Object, _cacheMock.Object, _dalServiceMock.Object, _userServiceMock.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteApproval_ValidApprovalID_DeletesApproval() {
|
||||||
|
int approvalID = 1;
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync(It.IsAny<string>(), It.IsAny<object>())).ReturnsAsync(1);
|
||||||
|
|
||||||
|
await _approvalService.DeleteApproval(approvalID);
|
||||||
|
|
||||||
|
_dalServiceMock.Verify(d => d.ExecuteAsync(It.IsAny<string>(), It.IsAny<object>()), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteApproval_InvalidApprovalID_ThrowsArgumentException() {
|
||||||
|
int approvalID = 0;
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<ArgumentException>(() => _approvalService.DeleteApproval(approvalID));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteApproval_DeletionFails_ThrowsException() {
|
||||||
|
int approvalID = 1;
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync(It.IsAny<string>(), It.IsAny<object>())).ReturnsAsync(0);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _approvalService.DeleteApproval(approvalID));
|
||||||
|
}
|
||||||
|
}
|
18
MesaFabApproval.API.Test/MockMemoryCacheService.cs
Normal file
18
MesaFabApproval.API.Test/MockMemoryCacheService.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
|
||||||
|
using Moq;
|
||||||
|
|
||||||
|
namespace MesaFabApproval.API.Test;
|
||||||
|
|
||||||
|
public static class MockMemoryCacheService {
|
||||||
|
public static Mock<IMemoryCache> GetMemoryCache(object expectedValue) {
|
||||||
|
Mock<IMemoryCache> mockMemoryCache = new Mock<IMemoryCache>();
|
||||||
|
mockMemoryCache
|
||||||
|
.Setup(x => x.TryGetValue(It.IsAny<object>(), out expectedValue))
|
||||||
|
.Returns(true);
|
||||||
|
mockMemoryCache
|
||||||
|
.Setup(x => x.CreateEntry(It.IsAny<object>()))
|
||||||
|
.Returns(Mock.Of<ICacheEntry>());
|
||||||
|
return mockMemoryCache;
|
||||||
|
}
|
||||||
|
}
|
196
MesaFabApproval.API.Test/PCRBFollowUpCommentsTests.cs
Normal file
196
MesaFabApproval.API.Test/PCRBFollowUpCommentsTests.cs
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
using MesaFabApproval.API.Services;
|
||||||
|
using MesaFabApproval.Models;
|
||||||
|
using MesaFabApproval.Shared.Models;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
using Moq;
|
||||||
|
|
||||||
|
namespace MesaFabApproval.API.Test;
|
||||||
|
|
||||||
|
public class PCRBFollowUpCommentsTests {
|
||||||
|
private readonly Mock<ILogger<PCRBService>> _loggerMock;
|
||||||
|
private readonly Mock<IDalService> _dalServiceMock;
|
||||||
|
private readonly Mock<IMemoryCache> _cacheMock;
|
||||||
|
private readonly Mock<IUserService> _userServiceMock;
|
||||||
|
private readonly Mock<IApprovalService> _approvalServiceMock;
|
||||||
|
private readonly Mock<ISmtpService> _smtpServiceMock;
|
||||||
|
private readonly PCRBService _pcrbService;
|
||||||
|
private readonly AppSettings _appSettings;
|
||||||
|
|
||||||
|
private static PCRBFollowUpComment FOLLOW_UP_COMMENT = new PCRBFollowUpComment {
|
||||||
|
PlanNumber = 1,
|
||||||
|
FollowUpID = 1,
|
||||||
|
Comment = "Comment",
|
||||||
|
UserID = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
private static IEnumerable<PCRBFollowUpComment> FOLLOW_UP_COMMENTS = new List<PCRBFollowUpComment>() { FOLLOW_UP_COMMENT };
|
||||||
|
|
||||||
|
public PCRBFollowUpCommentsTests() {
|
||||||
|
_loggerMock = new Mock<ILogger<PCRBService>>();
|
||||||
|
_dalServiceMock = new Mock<IDalService>();
|
||||||
|
_userServiceMock = new Mock<IUserService>();
|
||||||
|
_approvalServiceMock = new Mock<IApprovalService>();
|
||||||
|
_smtpServiceMock = new Mock<ISmtpService>();
|
||||||
|
_cacheMock = MockMemoryCacheService.GetMemoryCache(FOLLOW_UP_COMMENTS);
|
||||||
|
_appSettings = new AppSettings(
|
||||||
|
Company: "Infineon",
|
||||||
|
DbConnectionString: "connectionString",
|
||||||
|
JwtAudience: "audience",
|
||||||
|
JwtIssuer: "issuer",
|
||||||
|
JwtKey: "key",
|
||||||
|
MrbAttachmentPath: "mrbAttachmentPath",
|
||||||
|
PcrbAttachmentPath: "pcrbAttachmentPath",
|
||||||
|
ShouldSendEmail: false,
|
||||||
|
SiteBaseUrl: "siteBaseUrl",
|
||||||
|
WorkingDirectoryName: "workingDirectoryName"
|
||||||
|
);
|
||||||
|
|
||||||
|
_pcrbService = new PCRBService(
|
||||||
|
_loggerMock.Object,
|
||||||
|
_dalServiceMock.Object,
|
||||||
|
_cacheMock.Object,
|
||||||
|
_userServiceMock.Object,
|
||||||
|
_approvalServiceMock.Object,
|
||||||
|
_smtpServiceMock.Object,
|
||||||
|
_appSettings
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateFollowUpComment_WithValidParam_ShouldCreateFollowUp() {
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync<PCRBFollowUpComment>(It.IsAny<string>(), FOLLOW_UP_COMMENT))
|
||||||
|
.ReturnsAsync(1);
|
||||||
|
|
||||||
|
await _pcrbService.CreateFollowUpComment(FOLLOW_UP_COMMENT);
|
||||||
|
|
||||||
|
_dalServiceMock.Verify(d => d.ExecuteAsync<PCRBFollowUpComment>(It.IsAny<string>(), FOLLOW_UP_COMMENT), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateFollowUpComment_WithNullParam_ShouldThrowException() {
|
||||||
|
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.CreateFollowUpComment(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateFollowUpComment_WithDatabaseFailure_ShouldThrowException() {
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync<PCRBFollowUpComment>(It.IsAny<string>(), FOLLOW_UP_COMMENT))
|
||||||
|
.ReturnsAsync(0);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.CreateFollowUpComment(FOLLOW_UP_COMMENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateFollowUpComment_WithDatabaseException_ShouldThrowException() {
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync<PCRBFollowUpComment>(It.IsAny<string>(), FOLLOW_UP_COMMENT))
|
||||||
|
.Throws<Exception>();
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.CreateFollowUpComment(FOLLOW_UP_COMMENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetFollowUpCommentsByPlanNumber_WithCacheBypass_ShouldReturnFollowUps() {
|
||||||
|
int planNumber = 1;
|
||||||
|
|
||||||
|
_dalServiceMock.Setup(d => d.QueryAsync<PCRBFollowUpComment>(It.IsAny<string>(), It.IsAny<object>()))
|
||||||
|
.ReturnsAsync(FOLLOW_UP_COMMENTS);
|
||||||
|
|
||||||
|
IEnumerable<PCRBFollowUpComment> result = await _pcrbService.GetFollowUpCommentsByPlanNumber(planNumber, true);
|
||||||
|
|
||||||
|
Assert.NotNull(result);
|
||||||
|
Assert.Single(result);
|
||||||
|
Assert.Equal(FOLLOW_UP_COMMENTS, result);
|
||||||
|
_dalServiceMock.Verify(d => d.QueryAsync<PCRBFollowUpComment>(It.IsAny<string>(), It.IsAny<object>()), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetFollowUpCommentsByPlanNumber_WithCacheBypass_AndDatabaseException_ShouldThrowException() {
|
||||||
|
int planNumber = 1;
|
||||||
|
|
||||||
|
_dalServiceMock.Setup(d => d.QueryAsync<PCRBFollowUpComment>(It.IsAny<string>(), It.IsAny<object>()))
|
||||||
|
.Throws<Exception>();
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.GetFollowUpCommentsByPlanNumber(planNumber, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetFollowUpCommentsByPlanNumber_WithoutCacheBypass_ShouldReturnFollowUps() {
|
||||||
|
int planNumber = 1;
|
||||||
|
|
||||||
|
IEnumerable<PCRBFollowUpComment> result = await _pcrbService.GetFollowUpCommentsByPlanNumber(planNumber, false);
|
||||||
|
|
||||||
|
Assert.NotNull(result);
|
||||||
|
Assert.Single(result);
|
||||||
|
Assert.Equal(FOLLOW_UP_COMMENTS, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateFollowUpComment_WithValidParam_ShouldUpdateFollowUp() {
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync<PCRBFollowUpComment>(It.IsAny<string>(), FOLLOW_UP_COMMENT))
|
||||||
|
.ReturnsAsync(1);
|
||||||
|
|
||||||
|
await _pcrbService.UpdateFollowUpComment(FOLLOW_UP_COMMENT);
|
||||||
|
|
||||||
|
_dalServiceMock.Verify(d => d.ExecuteAsync<PCRBFollowUpComment>(It.IsAny<string>(), FOLLOW_UP_COMMENT), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateFollowUpComment_WithNullParam_ShouldThrowException() {
|
||||||
|
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.UpdateFollowUpComment(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateFollowUpComment_WithDatabaseFailure_ShouldThrowException() {
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync<PCRBFollowUpComment>(It.IsAny<string>(), FOLLOW_UP_COMMENT))
|
||||||
|
.ReturnsAsync(0);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.UpdateFollowUpComment(FOLLOW_UP_COMMENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateFollowUpComment_WithDatabaseException_ShouldThrowException() {
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync<PCRBFollowUpComment>(It.IsAny<string>(), FOLLOW_UP_COMMENT))
|
||||||
|
.Throws<Exception>();
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.UpdateFollowUpComment(FOLLOW_UP_COMMENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteFollowUpComment_WithValidId_ShouldDeleteFollowUp() {
|
||||||
|
int commentId = 1;
|
||||||
|
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync(It.IsAny<string>(), It.IsAny<object>()))
|
||||||
|
.ReturnsAsync(1);
|
||||||
|
|
||||||
|
await _pcrbService.DeleteFollowUpComment(commentId);
|
||||||
|
|
||||||
|
_dalServiceMock.Verify(d => d.ExecuteAsync(It.IsAny<string>(), It.IsAny<object>()), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteFollowUpComment_WithInvalidId_ShouldThrowException() {
|
||||||
|
await Assert.ThrowsAsync<ArgumentException>(() => _pcrbService.DeleteFollowUpComment(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteFollowUpComment_WithDatabaseFailure_ShouldThrowException() {
|
||||||
|
int commentId = 1;
|
||||||
|
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync(It.IsAny<string>(), It.IsAny<object>()))
|
||||||
|
.ReturnsAsync(0);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.DeleteFollowUpComment(commentId));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteFollowUpComment_WithDatabaseException_ShouldThrowException() {
|
||||||
|
int commentId = 1;
|
||||||
|
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync(It.IsAny<string>(), It.IsAny<object>()))
|
||||||
|
.Throws<Exception>();
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.DeleteFollowUpComment(commentId));
|
||||||
|
}
|
||||||
|
}
|
198
MesaFabApproval.API.Test/PCRBFollowUpTests.cs
Normal file
198
MesaFabApproval.API.Test/PCRBFollowUpTests.cs
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
using MesaFabApproval.API.Services;
|
||||||
|
using MesaFabApproval.Models;
|
||||||
|
using MesaFabApproval.Shared.Models;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
using Moq;
|
||||||
|
|
||||||
|
namespace MesaFabApproval.API.Test;
|
||||||
|
|
||||||
|
public class PCRBFollowUpTests {
|
||||||
|
private readonly Mock<ILogger<PCRBService>> _loggerMock;
|
||||||
|
private readonly Mock<IDalService> _dalServiceMock;
|
||||||
|
private readonly Mock<IMemoryCache> _cacheMock;
|
||||||
|
private readonly Mock<IUserService> _userServiceMock;
|
||||||
|
private readonly Mock<IApprovalService> _approvalServiceMock;
|
||||||
|
private readonly Mock<ISmtpService> _smtpServiceMock;
|
||||||
|
private readonly PCRBService _pcrbService;
|
||||||
|
private readonly AppSettings _appSettings;
|
||||||
|
|
||||||
|
private static PCRBFollowUp FOLLOW_UP = new PCRBFollowUp {
|
||||||
|
ID = 1,
|
||||||
|
PlanNumber = 1,
|
||||||
|
Step = 1,
|
||||||
|
FollowUpDate = DateTime.Now
|
||||||
|
};
|
||||||
|
|
||||||
|
private static IEnumerable<PCRBFollowUp> FOLLOW_UPS = new List<PCRBFollowUp>() {
|
||||||
|
new PCRBFollowUp { ID = 1, PlanNumber = 1, Step = 1, FollowUpDate = DateTime.Now }
|
||||||
|
};
|
||||||
|
|
||||||
|
public PCRBFollowUpTests() {
|
||||||
|
_loggerMock = new Mock<ILogger<PCRBService>>();
|
||||||
|
_dalServiceMock = new Mock<IDalService>();
|
||||||
|
_userServiceMock = new Mock<IUserService>();
|
||||||
|
_approvalServiceMock = new Mock<IApprovalService>();
|
||||||
|
_smtpServiceMock = new Mock<ISmtpService>();
|
||||||
|
_cacheMock = MockMemoryCacheService.GetMemoryCache(FOLLOW_UPS);
|
||||||
|
_appSettings = new AppSettings(
|
||||||
|
Company: "Infineon",
|
||||||
|
DbConnectionString: "connectionString",
|
||||||
|
JwtAudience: "audience",
|
||||||
|
JwtIssuer: "issuer",
|
||||||
|
JwtKey: "key",
|
||||||
|
MrbAttachmentPath: "mrbAttachmentPath",
|
||||||
|
PcrbAttachmentPath: "pcrbAttachmentPath",
|
||||||
|
ShouldSendEmail: false,
|
||||||
|
SiteBaseUrl: "siteBaseUrl",
|
||||||
|
WorkingDirectoryName: "workingDirectoryName"
|
||||||
|
);
|
||||||
|
|
||||||
|
_pcrbService = new PCRBService(
|
||||||
|
_loggerMock.Object,
|
||||||
|
_dalServiceMock.Object,
|
||||||
|
_cacheMock.Object,
|
||||||
|
_userServiceMock.Object,
|
||||||
|
_approvalServiceMock.Object,
|
||||||
|
_smtpServiceMock.Object,
|
||||||
|
_appSettings
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateFollowUp_WithValidParam_ShouldCreateFollowUp() {
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync<PCRBFollowUp>(It.IsAny<string>(), FOLLOW_UP))
|
||||||
|
.ReturnsAsync(1);
|
||||||
|
|
||||||
|
await _pcrbService.CreateFollowUp(FOLLOW_UP);
|
||||||
|
|
||||||
|
_dalServiceMock.Verify(d => d.ExecuteAsync<PCRBFollowUp>(It.IsAny<string>(), FOLLOW_UP), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateFollowUp_WithNullParam_ShouldThrowException() {
|
||||||
|
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.CreateFollowUp(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateFollowUp_WithDatabaseFailure_ShouldThrowException() {
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync<PCRBFollowUp>(It.IsAny<string>(), FOLLOW_UP))
|
||||||
|
.ReturnsAsync(0);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.CreateFollowUp(FOLLOW_UP));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateFollowUp_WithDatabaseException_ShouldThrowException() {
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync<PCRBFollowUp>(It.IsAny<string>(), FOLLOW_UP))
|
||||||
|
.Throws<Exception>();
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.CreateFollowUp(FOLLOW_UP));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetFollowUpsByPlanNumber_WithCacheBypass_ShouldReturnFollowUps() {
|
||||||
|
int planNumber = 1;
|
||||||
|
|
||||||
|
_dalServiceMock.Setup(d => d.QueryAsync<PCRBFollowUp>(It.IsAny<string>(), It.IsAny<object>()))
|
||||||
|
.ReturnsAsync(FOLLOW_UPS);
|
||||||
|
|
||||||
|
IEnumerable<PCRBFollowUp> result = await _pcrbService.GetFollowUpsByPlanNumber(planNumber, true);
|
||||||
|
|
||||||
|
Assert.NotNull(result);
|
||||||
|
Assert.Single(result);
|
||||||
|
Assert.Equal(FOLLOW_UPS, result);
|
||||||
|
_dalServiceMock.Verify(d => d.QueryAsync<PCRBFollowUp>(It.IsAny<string>(), It.IsAny<object>()), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetFollowUpsByPlanNumber_WithCacheBypass_AndDatabaseException_ShouldThrowException() {
|
||||||
|
int planNumber = 1;
|
||||||
|
|
||||||
|
_dalServiceMock.Setup(d => d.QueryAsync<PCRBFollowUp>(It.IsAny<string>(), It.IsAny<object>()))
|
||||||
|
.Throws<Exception>();
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.GetFollowUpsByPlanNumber(planNumber, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetFollowUpsByPlanNumber_WithoutCacheBypass_ShouldReturnFollowUps() {
|
||||||
|
int planNumber = 1;
|
||||||
|
|
||||||
|
IEnumerable<PCRBFollowUp> result = await _pcrbService.GetFollowUpsByPlanNumber(planNumber, false);
|
||||||
|
|
||||||
|
Assert.NotNull(result);
|
||||||
|
Assert.Single(result);
|
||||||
|
Assert.Equal(FOLLOW_UPS, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateFollowUp_WithValidParam_ShouldUpdateFollowUp() {
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync<PCRBFollowUp>(It.IsAny<string>(), FOLLOW_UP))
|
||||||
|
.ReturnsAsync(1);
|
||||||
|
|
||||||
|
await _pcrbService.UpdateFollowUp(FOLLOW_UP);
|
||||||
|
|
||||||
|
_dalServiceMock.Verify(d => d.ExecuteAsync<PCRBFollowUp>(It.IsAny<string>(), FOLLOW_UP), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateFollowUp_WithNullParam_ShouldThrowException() {
|
||||||
|
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.UpdateFollowUp(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateFollowUp_WithDatabaseFailure_ShouldThrowException() {
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync<PCRBFollowUp>(It.IsAny<string>(), FOLLOW_UP))
|
||||||
|
.ReturnsAsync(0);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.UpdateFollowUp(FOLLOW_UP));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateFollowUp_WithDatabaseException_ShouldThrowException() {
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync<PCRBFollowUp>(It.IsAny<string>(), FOLLOW_UP))
|
||||||
|
.Throws<Exception>();
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.UpdateFollowUp(FOLLOW_UP));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteFollowUp_WithValidId_ShouldDeleteFollowUp() {
|
||||||
|
int followUpId = 1;
|
||||||
|
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync(It.IsAny<string>(), It.IsAny<object>()))
|
||||||
|
.ReturnsAsync(1);
|
||||||
|
|
||||||
|
await _pcrbService.DeleteFollowUp(followUpId);
|
||||||
|
|
||||||
|
_dalServiceMock.Verify(d => d.ExecuteAsync(It.IsAny<string>(), It.IsAny<object>()), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteFollowUp_WithInvalidId_ShouldThrowException() {
|
||||||
|
await Assert.ThrowsAsync<ArgumentException>(() => _pcrbService.DeleteFollowUp(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteFollowUp_WithDatabaseFailure_ShouldThrowException() {
|
||||||
|
int followUpId = 1;
|
||||||
|
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync(It.IsAny<string>(), It.IsAny<object>()))
|
||||||
|
.ReturnsAsync(0);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.DeleteFollowUp(followUpId));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteFollowUp_WithDatabaseException_ShouldThrowException() {
|
||||||
|
int followUpId = 1;
|
||||||
|
|
||||||
|
_dalServiceMock.Setup(d => d.ExecuteAsync(It.IsAny<string>(), It.IsAny<object>()))
|
||||||
|
.Throws<Exception>();
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.DeleteFollowUp(followUpId));
|
||||||
|
}
|
||||||
|
}
|
@ -1,28 +1,15 @@
|
|||||||
using MesaFabApproval.API.Services;
|
using MesaFabApproval.API.Services;
|
||||||
using MesaFabApproval.Models;
|
using MesaFabApproval.Models;
|
||||||
using MesaFabApproval.Shared.Models;
|
using MesaFabApproval.Shared.Models;
|
||||||
|
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
using Moq;
|
using Moq;
|
||||||
|
|
||||||
|
using System.Net.Mail;
|
||||||
|
|
||||||
namespace MesaFabApproval.API.Test;
|
namespace MesaFabApproval.API.Test;
|
||||||
|
public class PCRBServiceTests
|
||||||
public static class MockMemoryCacheService {
|
{
|
||||||
public static Mock<IMemoryCache> GetMemoryCache(object expectedValue) {
|
|
||||||
Mock<IMemoryCache> mockMemoryCache = new Mock<IMemoryCache>();
|
|
||||||
mockMemoryCache
|
|
||||||
.Setup(x => x.TryGetValue(It.IsAny<object>(), out expectedValue))
|
|
||||||
.Returns(true);
|
|
||||||
mockMemoryCache
|
|
||||||
.Setup(x => x.CreateEntry(It.IsAny<object>()))
|
|
||||||
.Returns(Mock.Of<ICacheEntry>());
|
|
||||||
return mockMemoryCache;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PCRBServiceTests {
|
|
||||||
private readonly Mock<ILogger<PCRBService>> _loggerMock;
|
private readonly Mock<ILogger<PCRBService>> _loggerMock;
|
||||||
private readonly Mock<IDalService> _dalServiceMock;
|
private readonly Mock<IDalService> _dalServiceMock;
|
||||||
private Mock<IMemoryCache> _cacheMock;
|
private Mock<IMemoryCache> _cacheMock;
|
||||||
@ -47,24 +34,25 @@ public class PCRBServiceTests {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static IEnumerable<PCRBFollowUp> FOLLOW_UPS = new List<PCRBFollowUp>() {
|
private static IEnumerable<PCRBFollowUp> FOLLOW_UPS = new List<PCRBFollowUp>() {
|
||||||
new PCRBFollowUp { ID = 1, PlanNumber = 1, Step = 1, FollowUpDate = DateTime.Now }
|
new PCRBFollowUp { ID = 1, PlanNumber = 1, Step = 1, FollowUpDate = DateTime.Now }
|
||||||
};
|
};
|
||||||
|
|
||||||
private static AppSettings appSettings = new AppSettings(
|
private static AppSettings appSettings = new AppSettings(
|
||||||
Company: "Infineon",
|
Company: "Infineon",
|
||||||
DbConnectionString: "connectionString",
|
DbConnectionString: "connectionString",
|
||||||
JwtAudience: "audience",
|
JwtAudience: "audience",
|
||||||
JwtIssuer: "issuer",
|
JwtIssuer: "issuer",
|
||||||
JwtKey: "key",
|
JwtKey: "key",
|
||||||
MrbAttachmentPath: "mrbAttachmentPath",
|
MrbAttachmentPath: "mrbAttachmentPath",
|
||||||
PcrbAttachmentPath: "pcrbAttachmentPath",
|
PcrbAttachmentPath: "pcrbAttachmentPath",
|
||||||
ShouldSendEmail: false,
|
ShouldSendEmail: false,
|
||||||
SiteBaseUrl: "siteBaseUrl",
|
SiteBaseUrl: "siteBaseUrl",
|
||||||
WorkingDirectoryName: "workingDirectoryName"
|
WorkingDirectoryName: "workingDirectoryName"
|
||||||
);
|
);
|
||||||
|
|
||||||
public PCRBServiceTests() {
|
public PCRBServiceTests()
|
||||||
|
{
|
||||||
_loggerMock = new Mock<ILogger<PCRBService>>();
|
_loggerMock = new Mock<ILogger<PCRBService>>();
|
||||||
_dalServiceMock = new Mock<IDalService>();
|
_dalServiceMock = new Mock<IDalService>();
|
||||||
_userServiceMock = new Mock<IUserService>();
|
_userServiceMock = new Mock<IUserService>();
|
||||||
@ -84,8 +72,10 @@ public class PCRBServiceTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task CreateNewPCRB_WithValidParam_ShouldCreatePCRB() {
|
public async Task CreateNewPCRB_WithValidParam_ShouldCreatePCRB()
|
||||||
var pcrb = new PCRB {
|
{
|
||||||
|
var pcrb = new PCRB
|
||||||
|
{
|
||||||
OwnerID = 1,
|
OwnerID = 1,
|
||||||
Title = "Test Title",
|
Title = "Test Title",
|
||||||
ChangeLevel = "Level 1",
|
ChangeLevel = "Level 1",
|
||||||
@ -107,13 +97,16 @@ public class PCRBServiceTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task CreateNewPCRB_WithNullParam_ShouldThrowException() {
|
public async Task CreateNewPCRB_WithNullParam_ShouldThrowException()
|
||||||
|
{
|
||||||
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.CreateNewPCRB(null));
|
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.CreateNewPCRB(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task CreateNewPCRB_WithDatabaseFailure_ShouldThrowException() {
|
public async Task CreateNewPCRB_WithDatabaseFailure_ShouldThrowException()
|
||||||
var pcrb = new PCRB {
|
{
|
||||||
|
var pcrb = new PCRB
|
||||||
|
{
|
||||||
OwnerID = 1,
|
OwnerID = 1,
|
||||||
Title = "Test Title",
|
Title = "Test Title",
|
||||||
ChangeLevel = "Level 1",
|
ChangeLevel = "Level 1",
|
||||||
@ -133,8 +126,10 @@ public class PCRBServiceTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task CreateNewPCRB_WithDatabaseException_ShouldThrowException() {
|
public async Task CreateNewPCRB_WithDatabaseException_ShouldThrowException()
|
||||||
var pcrb = new PCRB {
|
{
|
||||||
|
var pcrb = new PCRB
|
||||||
|
{
|
||||||
OwnerID = 1,
|
OwnerID = 1,
|
||||||
Title = "Test Title",
|
Title = "Test Title",
|
||||||
ChangeLevel = "Level 1",
|
ChangeLevel = "Level 1",
|
||||||
@ -154,7 +149,8 @@ public class PCRBServiceTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task UpdatePCRB_WithValidParam_ShouldUpdatePCRB() {
|
public async Task UpdatePCRB_WithValidParam_ShouldUpdatePCRB()
|
||||||
|
{
|
||||||
_cacheMock = MockMemoryCacheService.GetMemoryCache(PCRBS);
|
_cacheMock = MockMemoryCacheService.GetMemoryCache(PCRBS);
|
||||||
|
|
||||||
_pcrbService = new PCRBService(
|
_pcrbService = new PCRBService(
|
||||||
@ -167,7 +163,8 @@ public class PCRBServiceTests {
|
|||||||
appSettings
|
appSettings
|
||||||
);
|
);
|
||||||
|
|
||||||
var pcrb = new PCRB {
|
var pcrb = new PCRB
|
||||||
|
{
|
||||||
PlanNumber = 1,
|
PlanNumber = 1,
|
||||||
OwnerID = 1,
|
OwnerID = 1,
|
||||||
Title = "Test Title",
|
Title = "Test Title",
|
||||||
@ -190,13 +187,16 @@ public class PCRBServiceTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task UpdatePCRB_WithNullParam_ShouldThrowException() {
|
public async Task UpdatePCRB_WithNullParam_ShouldThrowException()
|
||||||
|
{
|
||||||
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.UpdatePCRB(null));
|
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.UpdatePCRB(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task UpdatePCRB_WithDatabaseFailure_ShouldThrowException() {
|
public async Task UpdatePCRB_WithDatabaseFailure_ShouldThrowException()
|
||||||
var pcrb = new PCRB {
|
{
|
||||||
|
var pcrb = new PCRB
|
||||||
|
{
|
||||||
PlanNumber = 1,
|
PlanNumber = 1,
|
||||||
OwnerID = 1,
|
OwnerID = 1,
|
||||||
Title = "Test Title",
|
Title = "Test Title",
|
||||||
@ -217,8 +217,10 @@ public class PCRBServiceTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task UpdatePCRB_WithDatabaseException_ShouldThrowException() {
|
public async Task UpdatePCRB_WithDatabaseException_ShouldThrowException()
|
||||||
var pcrb = new PCRB {
|
{
|
||||||
|
var pcrb = new PCRB
|
||||||
|
{
|
||||||
PlanNumber = 1,
|
PlanNumber = 1,
|
||||||
OwnerID = 1,
|
OwnerID = 1,
|
||||||
Title = "Test Title",
|
Title = "Test Title",
|
||||||
@ -239,176 +241,88 @@ public class PCRBServiceTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task CreateFollowUp_WithValidParam_ShouldCreateFollowUp() {
|
public async Task NotifyApprover_ShouldSendNotification()
|
||||||
var followUp = new PCRBFollowUp {
|
{
|
||||||
PlanNumber = 1,
|
PCRBNotification notification = new PCRBNotification
|
||||||
Step = 1,
|
{
|
||||||
FollowUpDate = DateTime.Now
|
Message = "Test Message",
|
||||||
|
PCRB = new PCRB { PlanNumber = 1, Title = "Test PCRB" },
|
||||||
|
Approval = new Approval
|
||||||
|
{
|
||||||
|
UserID = 1,
|
||||||
|
IssueID = 1,
|
||||||
|
RoleName = "Role",
|
||||||
|
SubRole = "SubRole",
|
||||||
|
SubRoleID = 1,
|
||||||
|
AssignedDate = DateTime.Now
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_dalServiceMock.Setup(d => d.ExecuteAsync<PCRBFollowUp>(It.IsAny<string>(), followUp))
|
_userServiceMock.Setup(s => s.GetUserByUserId(It.IsAny<int>()))
|
||||||
.ReturnsAsync(1);
|
.ReturnsAsync(new User
|
||||||
|
{
|
||||||
|
UserID = 1,
|
||||||
|
LoginID = "testLogin",
|
||||||
|
FirstName = "Test",
|
||||||
|
LastName = "User",
|
||||||
|
Email = "test@example.com"
|
||||||
|
});
|
||||||
|
|
||||||
await _pcrbService.CreateFollowUp(followUp);
|
_smtpServiceMock.Setup(s => s.SendEmail(It.IsAny<IEnumerable<MailAddress>>(),
|
||||||
|
It.IsAny<IEnumerable<MailAddress>>(),
|
||||||
|
It.IsAny<string>(),
|
||||||
|
It.IsAny<string>()))
|
||||||
|
.ReturnsAsync(true);
|
||||||
|
|
||||||
_dalServiceMock.Verify(d => d.ExecuteAsync<PCRBFollowUp>(It.IsAny<string>(), followUp), Times.Once);
|
_approvalServiceMock.Setup(s => s.UpdateApproval(It.IsAny<Approval>()))
|
||||||
|
.Returns(Task.CompletedTask);
|
||||||
|
|
||||||
|
await _pcrbService.NotifyApprover(notification);
|
||||||
|
|
||||||
|
_smtpServiceMock.Verify(s => s.SendEmail(It.IsAny<IEnumerable<MailAddress>>(),
|
||||||
|
It.IsAny<IEnumerable<MailAddress>>(),
|
||||||
|
It.IsAny<string>(),
|
||||||
|
It.IsAny<string>()), Times.Once);
|
||||||
|
_approvalServiceMock.Verify(s => s.UpdateApproval(It.IsAny<Approval>()), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task CreateFollowUp_WithNullParam_ShouldThrowException() {
|
public async Task NotifyApprover_ShouldThrowException_WhenNotificationIsNull()
|
||||||
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.CreateFollowUp(null));
|
{
|
||||||
|
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.NotifyApprover(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task CreateFollowUp_WithDatabaseFailure_ShouldThrowException() {
|
public async Task NotifyApprover_ShouldThrowException_WhenPCRBIsNull()
|
||||||
var followUp = new PCRBFollowUp {
|
{
|
||||||
PlanNumber = 1,
|
PCRBNotification notification = new PCRBNotification
|
||||||
Step = 1,
|
{
|
||||||
FollowUpDate = DateTime.Now
|
Message = "Test Message",
|
||||||
|
PCRB = null,
|
||||||
|
Approval = new Approval
|
||||||
|
{
|
||||||
|
UserID = 1,
|
||||||
|
IssueID = 1,
|
||||||
|
RoleName = "Role",
|
||||||
|
SubRole = "SubRole",
|
||||||
|
SubRoleID = 1,
|
||||||
|
AssignedDate = DateTime.Now
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_dalServiceMock.Setup(d => d.ExecuteAsync<PCRBFollowUp>(It.IsAny<string>(), followUp))
|
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.NotifyApprover(notification));
|
||||||
.ReturnsAsync(0);
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<Exception>(() => _pcrbService.CreateFollowUp(followUp));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task CreateFollowUp_WithDatabaseException_ShouldThrowException() {
|
public async Task NotifyApprover_ShouldThrowException_WhenApprovalIsNull()
|
||||||
var followUp = new PCRBFollowUp {
|
{
|
||||||
PlanNumber = 1,
|
PCRBNotification notification = new PCRBNotification
|
||||||
Step = 1,
|
{
|
||||||
FollowUpDate = DateTime.Now
|
Message = "Test Message",
|
||||||
|
PCRB = new PCRB { PlanNumber = 1, Title = "Test PCRB" },
|
||||||
|
Approval = null
|
||||||
};
|
};
|
||||||
|
|
||||||
_dalServiceMock.Setup(d => d.ExecuteAsync<PCRBFollowUp>(It.IsAny<string>(), followUp))
|
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.NotifyApprover(notification));
|
||||||
.Throws<Exception>();
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<Exception>(() => _pcrbService.CreateFollowUp(followUp));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetFollowUpsByPlanNumber_WithCacheBypass_ShouldReturnFollowUps() {
|
|
||||||
int planNumber = 1;
|
|
||||||
|
|
||||||
_dalServiceMock.Setup(d => d.QueryAsync<PCRBFollowUp>(It.IsAny<string>(), It.IsAny<object>()))
|
|
||||||
.ReturnsAsync(FOLLOW_UPS);
|
|
||||||
|
|
||||||
IEnumerable<PCRBFollowUp> result = await _pcrbService.GetFollowUpsByPlanNumber(planNumber, true);
|
|
||||||
|
|
||||||
Assert.NotNull(result);
|
|
||||||
Assert.Single(result);
|
|
||||||
Assert.Equal(FOLLOW_UPS, result);
|
|
||||||
_dalServiceMock.Verify(d => d.QueryAsync<PCRBFollowUp>(It.IsAny<string>(), It.IsAny<object>()), Times.Once);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetFollowUpsByPlanNumber_WithCacheBypass_AndDatabaseException_ShouldThrowException() {
|
|
||||||
int planNumber = 1;
|
|
||||||
|
|
||||||
_dalServiceMock.Setup(d => d.QueryAsync<PCRBFollowUp>(It.IsAny<string>(), It.IsAny<object>()))
|
|
||||||
.Throws<Exception>();
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<Exception>(() => _pcrbService.GetFollowUpsByPlanNumber(planNumber, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetFollowUpsByPlanNumber_WithoutCacheBypass_ShouldReturnFollowUps() {
|
|
||||||
int planNumber = 1;
|
|
||||||
|
|
||||||
IEnumerable<PCRBFollowUp> result = await _pcrbService.GetFollowUpsByPlanNumber(planNumber, false);
|
|
||||||
|
|
||||||
Assert.NotNull(result);
|
|
||||||
Assert.Single(result);
|
|
||||||
Assert.Equal(FOLLOW_UPS, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task UpdateFollowUp_WithValidParam_ShouldUpdateFollowUp() {
|
|
||||||
var followUp = new PCRBFollowUp {
|
|
||||||
ID = 1,
|
|
||||||
PlanNumber = 1,
|
|
||||||
Step = 1,
|
|
||||||
FollowUpDate = DateTime.Now
|
|
||||||
};
|
|
||||||
|
|
||||||
_dalServiceMock.Setup(d => d.ExecuteAsync<PCRBFollowUp>(It.IsAny<string>(), followUp))
|
|
||||||
.ReturnsAsync(1);
|
|
||||||
|
|
||||||
await _pcrbService.UpdateFollowUp(followUp);
|
|
||||||
|
|
||||||
_dalServiceMock.Verify(d => d.ExecuteAsync<PCRBFollowUp>(It.IsAny<string>(), followUp), Times.Once);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task UpdateFollowUp_WithNullParam_ShouldThrowException() {
|
|
||||||
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.UpdateFollowUp(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task UpdateFollowUp_WithDatabaseFailure_ShouldThrowException() {
|
|
||||||
var followUp = new PCRBFollowUp {
|
|
||||||
ID = 1,
|
|
||||||
PlanNumber = 1,
|
|
||||||
Step = 1,
|
|
||||||
FollowUpDate = DateTime.Now
|
|
||||||
};
|
|
||||||
|
|
||||||
_dalServiceMock.Setup(d => d.ExecuteAsync<PCRBFollowUp>(It.IsAny<string>(), followUp))
|
|
||||||
.ReturnsAsync(0);
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<Exception>(() => _pcrbService.UpdateFollowUp(followUp));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task UpdateFollowUp_WithDatabaseException_ShouldThrowException() {
|
|
||||||
var followUp = new PCRBFollowUp {
|
|
||||||
ID = 1,
|
|
||||||
PlanNumber = 1,
|
|
||||||
Step = 1,
|
|
||||||
FollowUpDate = DateTime.Now
|
|
||||||
};
|
|
||||||
|
|
||||||
_dalServiceMock.Setup(d => d.ExecuteAsync<PCRBFollowUp>(It.IsAny<string>(), followUp))
|
|
||||||
.Throws<Exception>();
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<Exception>(() => _pcrbService.UpdateFollowUp(followUp));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task DeleteFollowUp_WithValidId_ShouldDeleteFollowUp() {
|
|
||||||
int followUpId = 1;
|
|
||||||
|
|
||||||
_dalServiceMock.Setup(d => d.ExecuteAsync(It.IsAny<string>(), It.IsAny<object>()))
|
|
||||||
.ReturnsAsync(1);
|
|
||||||
|
|
||||||
await _pcrbService.DeleteFollowUp(followUpId);
|
|
||||||
|
|
||||||
_dalServiceMock.Verify(d => d.ExecuteAsync(It.IsAny<string>(), It.IsAny<object>()), Times.Once);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task DeleteFollowUp_WithInvalidId_ShouldThrowException() {
|
|
||||||
await Assert.ThrowsAsync<ArgumentException>(() => _pcrbService.DeleteFollowUp(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task DeleteFollowUp_WithDatabaseFailure_ShouldThrowException() {
|
|
||||||
int followUpId = 1;
|
|
||||||
|
|
||||||
_dalServiceMock.Setup(d => d.ExecuteAsync(It.IsAny<string>(), It.IsAny<object>()))
|
|
||||||
.ReturnsAsync(0);
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<Exception>(() => _pcrbService.DeleteFollowUp(followUpId));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task DeleteFollowUp_WithDatabaseException_ShouldThrowException() {
|
|
||||||
int followUpId = 1;
|
|
||||||
|
|
||||||
_dalServiceMock.Setup(d => d.ExecuteAsync(It.IsAny<string>(), It.IsAny<object>()))
|
|
||||||
.Throws<Exception>();
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<Exception>(() => _pcrbService.DeleteFollowUp(followUpId));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using MesaFabApproval.API.Services;
|
using MesaFabApproval.API.Services;
|
||||||
|
using MesaFabApproval.API.Utilities;
|
||||||
using MesaFabApproval.Shared.Models;
|
using MesaFabApproval.Shared.Models;
|
||||||
using MesaFabApproval.Shared.Services;
|
using MesaFabApproval.Shared.Services;
|
||||||
|
|
||||||
@ -11,13 +12,13 @@ namespace MesaFabApproval.API.Controllers;
|
|||||||
public class ApprovalController : ControllerBase {
|
public class ApprovalController : ControllerBase {
|
||||||
private readonly ILogger<ApprovalController> _logger;
|
private readonly ILogger<ApprovalController> _logger;
|
||||||
private readonly IApprovalService _approvalService;
|
private readonly IApprovalService _approvalService;
|
||||||
private readonly IMonInWorkerClient _monInClient;
|
private readonly IMonInUtils _monInUtils;
|
||||||
|
|
||||||
public ApprovalController(ILogger<ApprovalController> logger, IApprovalService approvalService,
|
public ApprovalController(ILogger<ApprovalController> logger, IApprovalService approvalService,
|
||||||
IMonInWorkerClient monInClient) {
|
IMonInUtils monInUtils) {
|
||||||
_logger = logger ?? throw new ArgumentNullException("ILogger not injected");
|
_logger = logger ?? throw new ArgumentNullException("ILogger not injected");
|
||||||
_approvalService = approvalService ?? throw new ArgumentNullException("IApprovalService not injected");
|
_approvalService = approvalService ?? throw new ArgumentNullException("IApprovalService not injected");
|
||||||
_monInClient = monInClient ?? throw new ArgumentNullException("IMonInWorkerClient not injected");
|
_monInUtils = monInUtils ?? throw new ArgumentNullException("IMonInUtils not injected");
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
@ -39,26 +40,19 @@ public class ApprovalController : ControllerBase {
|
|||||||
} catch (ArgumentException ex) {
|
} catch (ArgumentException ex) {
|
||||||
isArgumentError = true;
|
isArgumentError = true;
|
||||||
errorMessage = ex.Message;
|
errorMessage = ex.Message;
|
||||||
|
_logger.LogWarning($"Argument error when attempting to create approval: {errorMessage}");
|
||||||
return BadRequest(errorMessage);
|
return BadRequest(errorMessage);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
isInternalError = true;
|
isInternalError = true;
|
||||||
errorMessage = $"Cannot create new approval, because {ex.Message}";
|
errorMessage = $"Cannot create new approval, because {ex.Message}";
|
||||||
|
_logger.LogError(errorMessage);
|
||||||
return Problem(errorMessage);
|
return Problem(errorMessage);
|
||||||
} finally {
|
} finally {
|
||||||
string metricName = "CreateApproval";
|
string metricName = "CreateApproval";
|
||||||
DateTime end = DateTime.Now;
|
DateTime end = DateTime.Now;
|
||||||
double millisecondsDiff = (end - start).TotalMilliseconds;
|
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||||
_monInClient.PostAverage(metricName + "Latency", millisecondsDiff);
|
|
||||||
|
_monInUtils.PostMetrics(metricName, millisecondsDiff, isArgumentError, isInternalError);
|
||||||
if (isArgumentError) {
|
|
||||||
_logger.LogWarning(errorMessage);
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
|
||||||
} else if (isInternalError) {
|
|
||||||
_logger.LogError(errorMessage);
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Critical);
|
|
||||||
} else {
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,26 +75,19 @@ public class ApprovalController : ControllerBase {
|
|||||||
} catch (ArgumentException ex) {
|
} catch (ArgumentException ex) {
|
||||||
isArgumentError = true;
|
isArgumentError = true;
|
||||||
errorMessage = ex.Message;
|
errorMessage = ex.Message;
|
||||||
|
_logger.LogWarning($"Argument error when getting approvals for issue {issueId}: {errorMessage}");
|
||||||
return BadRequest(errorMessage);
|
return BadRequest(errorMessage);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
isInternalError = true;
|
isInternalError = true;
|
||||||
errorMessage = $"Cannot get approvals, because {ex.Message}";
|
errorMessage = $"Cannot get approvals, because {ex.Message}";
|
||||||
|
_logger.LogError(errorMessage);
|
||||||
return Problem(errorMessage);
|
return Problem(errorMessage);
|
||||||
} finally {
|
} finally {
|
||||||
string metricName = "GetApprovalsForIssueId";
|
string metricName = "GetApprovalsForIssueId";
|
||||||
DateTime end = DateTime.Now;
|
DateTime end = DateTime.Now;
|
||||||
double millisecondsDiff = (end - start).TotalMilliseconds;
|
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||||
_monInClient.PostAverage(metricName + "Latency", millisecondsDiff);
|
|
||||||
|
_monInUtils.PostMetrics(metricName, millisecondsDiff, isArgumentError, isInternalError);
|
||||||
if (isArgumentError) {
|
|
||||||
_logger.LogWarning(errorMessage);
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
|
||||||
} else if (isInternalError) {
|
|
||||||
_logger.LogError(errorMessage);
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Critical);
|
|
||||||
} else {
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,26 +110,19 @@ public class ApprovalController : ControllerBase {
|
|||||||
} catch (ArgumentException ex) {
|
} catch (ArgumentException ex) {
|
||||||
isArgumentError = true;
|
isArgumentError = true;
|
||||||
errorMessage = ex.Message;
|
errorMessage = ex.Message;
|
||||||
|
_logger.LogWarning($"Argument error when getting approvals for user {userId}: {errorMessage}");
|
||||||
return BadRequest(errorMessage);
|
return BadRequest(errorMessage);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
isInternalError = true;
|
isInternalError = true;
|
||||||
errorMessage = $"Cannot get approvals, because {ex.Message}";
|
errorMessage = $"Cannot get approvals, because {ex.Message}";
|
||||||
|
_logger.LogError(errorMessage);
|
||||||
return Problem(errorMessage);
|
return Problem(errorMessage);
|
||||||
} finally {
|
} finally {
|
||||||
string metricName = "GetApprovalsForUserId";
|
string metricName = "GetApprovalsForUserId";
|
||||||
DateTime end = DateTime.Now;
|
DateTime end = DateTime.Now;
|
||||||
double millisecondsDiff = (end - start).TotalMilliseconds;
|
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||||
_monInClient.PostAverage(metricName + "Latency", millisecondsDiff);
|
|
||||||
|
_monInUtils.PostMetrics(metricName, millisecondsDiff, isArgumentError, isInternalError);
|
||||||
if (isArgumentError) {
|
|
||||||
_logger.LogWarning(errorMessage);
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
|
||||||
} else if (isInternalError) {
|
|
||||||
_logger.LogError(errorMessage);
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Critical);
|
|
||||||
} else {
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,26 +145,19 @@ public class ApprovalController : ControllerBase {
|
|||||||
} catch (ArgumentException ex) {
|
} catch (ArgumentException ex) {
|
||||||
isArgumentError = true;
|
isArgumentError = true;
|
||||||
errorMessage = ex.Message;
|
errorMessage = ex.Message;
|
||||||
|
_logger.LogWarning($"Argument error when getting approval group members for sub role {subRoleId}: {errorMessage}");
|
||||||
return BadRequest(errorMessage);
|
return BadRequest(errorMessage);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
isInternalError = true;
|
isInternalError = true;
|
||||||
errorMessage = $"Cannot get approval group members, because {ex.Message}";
|
errorMessage = $"Cannot get approval group members, because {ex.Message}";
|
||||||
|
_logger.LogError(errorMessage);
|
||||||
return Problem(errorMessage);
|
return Problem(errorMessage);
|
||||||
} finally {
|
} finally {
|
||||||
string metricName = "GetApprovalsGroupMembers";
|
string metricName = "GetApprovalsGroupMembers";
|
||||||
DateTime end = DateTime.Now;
|
DateTime end = DateTime.Now;
|
||||||
double millisecondsDiff = (end - start).TotalMilliseconds;
|
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||||
_monInClient.PostAverage(metricName + "Latency", millisecondsDiff);
|
|
||||||
|
_monInUtils.PostMetrics(metricName, millisecondsDiff, isArgumentError, isInternalError);
|
||||||
if (isArgumentError) {
|
|
||||||
_logger.LogWarning(errorMessage);
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
|
||||||
} else if (isInternalError) {
|
|
||||||
_logger.LogError(errorMessage);
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Critical);
|
|
||||||
} else {
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,7 +170,7 @@ public class ApprovalController : ControllerBase {
|
|||||||
string errorMessage = "";
|
string errorMessage = "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
_logger.LogInformation($"Attempting to update approval");
|
_logger.LogInformation("Attempting to update approval");
|
||||||
|
|
||||||
if (approval is null) throw new ArgumentNullException($"approval cannot be null");
|
if (approval is null) throw new ArgumentNullException($"approval cannot be null");
|
||||||
|
|
||||||
@ -207,26 +180,54 @@ public class ApprovalController : ControllerBase {
|
|||||||
} catch (ArgumentException ex) {
|
} catch (ArgumentException ex) {
|
||||||
isArgumentError = true;
|
isArgumentError = true;
|
||||||
errorMessage = ex.Message;
|
errorMessage = ex.Message;
|
||||||
|
_logger.LogWarning($"Argument error when attempting to update approval: {errorMessage}");
|
||||||
return BadRequest(errorMessage);
|
return BadRequest(errorMessage);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
isInternalError = true;
|
isInternalError = true;
|
||||||
errorMessage = $"Cannot update approval, because {ex.Message}";
|
errorMessage = $"Cannot update approval, because {ex.Message}";
|
||||||
|
_logger.LogError(errorMessage);
|
||||||
return Problem(errorMessage);
|
return Problem(errorMessage);
|
||||||
} finally {
|
} finally {
|
||||||
string metricName = "UpdateApproval";
|
string metricName = "UpdateApproval";
|
||||||
DateTime end = DateTime.Now;
|
DateTime end = DateTime.Now;
|
||||||
double millisecondsDiff = (end - start).TotalMilliseconds;
|
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||||
_monInClient.PostAverage(metricName + "Latency", millisecondsDiff);
|
|
||||||
|
|
||||||
if (isArgumentError) {
|
_monInUtils.PostMetrics(metricName, millisecondsDiff, isArgumentError, isInternalError);
|
||||||
_logger.LogWarning(errorMessage);
|
}
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
}
|
||||||
} else if (isInternalError) {
|
|
||||||
_logger.LogError(errorMessage);
|
[HttpDelete]
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Critical);
|
[Route("approval")]
|
||||||
} else {
|
public async Task<IActionResult> DeleteApproval(int approvalID) {
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
DateTime start = DateTime.Now;
|
||||||
}
|
bool isArgumentError = false;
|
||||||
|
bool isInternalError = false;
|
||||||
|
string errorMessage = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
_logger.LogInformation($"Attempting to delete approval {approvalID}");
|
||||||
|
|
||||||
|
if (approvalID <= 0) throw new ArgumentException("Invalid approval ID");
|
||||||
|
|
||||||
|
await _approvalService.DeleteApproval(approvalID);
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
} catch (ArgumentException ex) {
|
||||||
|
isArgumentError = true;
|
||||||
|
errorMessage = ex.Message;
|
||||||
|
_logger.LogWarning($"Argument error when attempting to delete approval: {errorMessage}");
|
||||||
|
return BadRequest(errorMessage);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
isInternalError = true;
|
||||||
|
errorMessage = $"Cannot delete approval, because {ex.Message}";
|
||||||
|
_logger.LogError(errorMessage);
|
||||||
|
return Problem(errorMessage);
|
||||||
|
} finally {
|
||||||
|
string metricName = "UpdateApproval";
|
||||||
|
DateTime end = DateTime.Now;
|
||||||
|
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||||
|
|
||||||
|
_monInUtils.PostMetrics(metricName, millisecondsDiff, isArgumentError, isInternalError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,26 +250,19 @@ public class ApprovalController : ControllerBase {
|
|||||||
} catch (ArgumentException ex) {
|
} catch (ArgumentException ex) {
|
||||||
isArgumentError = true;
|
isArgumentError = true;
|
||||||
errorMessage = ex.Message;
|
errorMessage = ex.Message;
|
||||||
|
_logger.LogWarning($"Argument error when attempting to approve: {errorMessage}");
|
||||||
return BadRequest(errorMessage);
|
return BadRequest(errorMessage);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
isInternalError = true;
|
isInternalError = true;
|
||||||
errorMessage = $"Cannot approve, because {ex.Message}";
|
errorMessage = $"Cannot approve, because {ex.Message}";
|
||||||
|
_logger.LogError(errorMessage);
|
||||||
return Problem(errorMessage);
|
return Problem(errorMessage);
|
||||||
} finally {
|
} finally {
|
||||||
string metricName = "Approve";
|
string metricName = "Approve";
|
||||||
DateTime end = DateTime.Now;
|
DateTime end = DateTime.Now;
|
||||||
double millisecondsDiff = (end - start).TotalMilliseconds;
|
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||||
_monInClient.PostAverage(metricName + "Latency", millisecondsDiff);
|
|
||||||
|
|
||||||
if (isArgumentError) {
|
_monInUtils.PostMetrics(metricName, millisecondsDiff, isArgumentError, isInternalError);
|
||||||
_logger.LogWarning(errorMessage);
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
|
||||||
} else if (isInternalError) {
|
|
||||||
_logger.LogError(errorMessage);
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Critical);
|
|
||||||
} else {
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,26 +285,19 @@ public class ApprovalController : ControllerBase {
|
|||||||
} catch (ArgumentException ex) {
|
} catch (ArgumentException ex) {
|
||||||
isArgumentError = true;
|
isArgumentError = true;
|
||||||
errorMessage = ex.Message;
|
errorMessage = ex.Message;
|
||||||
|
_logger.LogWarning($"Argument error when attempting to deny approval: {errorMessage}");
|
||||||
return BadRequest(errorMessage);
|
return BadRequest(errorMessage);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
isInternalError = true;
|
isInternalError = true;
|
||||||
errorMessage = $"Approval denial failed, because {ex.Message}";
|
errorMessage = $"Approval denial failed, because {ex.Message}";
|
||||||
|
_logger.LogError(errorMessage);
|
||||||
return Problem(errorMessage);
|
return Problem(errorMessage);
|
||||||
} finally {
|
} finally {
|
||||||
string metricName = "Deny";
|
string metricName = "Deny";
|
||||||
DateTime end = DateTime.Now;
|
DateTime end = DateTime.Now;
|
||||||
double millisecondsDiff = (end - start).TotalMilliseconds;
|
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||||
_monInClient.PostAverage(metricName + "Latency", millisecondsDiff);
|
|
||||||
|
|
||||||
if (isArgumentError) {
|
_monInUtils.PostMetrics(metricName, millisecondsDiff, isArgumentError, isInternalError);
|
||||||
_logger.LogWarning(errorMessage);
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
|
||||||
} else if (isInternalError) {
|
|
||||||
_logger.LogError(errorMessage);
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Critical);
|
|
||||||
} else {
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,26 +320,19 @@ public class ApprovalController : ControllerBase {
|
|||||||
} catch (ArgumentException ex) {
|
} catch (ArgumentException ex) {
|
||||||
isArgumentError = true;
|
isArgumentError = true;
|
||||||
errorMessage = ex.Message;
|
errorMessage = ex.Message;
|
||||||
|
_logger.LogWarning($"Argument error when attempting to get role ID by role name: {errorMessage}");
|
||||||
return BadRequest(errorMessage);
|
return BadRequest(errorMessage);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
isInternalError = true;
|
isInternalError = true;
|
||||||
errorMessage = $"Cannot get role ID, because {ex.Message}";
|
errorMessage = $"Cannot get role ID, because {ex.Message}";
|
||||||
|
_logger.LogError(errorMessage);
|
||||||
return Problem(errorMessage);
|
return Problem(errorMessage);
|
||||||
} finally {
|
} finally {
|
||||||
string metricName = "GetRoleIdForRoleName";
|
string metricName = "GetRoleIdForRoleName";
|
||||||
DateTime end = DateTime.Now;
|
DateTime end = DateTime.Now;
|
||||||
double millisecondsDiff = (end - start).TotalMilliseconds;
|
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||||
_monInClient.PostAverage(metricName + "Latency", millisecondsDiff);
|
|
||||||
|
|
||||||
if (isArgumentError) {
|
_monInUtils.PostMetrics(metricName, millisecondsDiff, isArgumentError, isInternalError);
|
||||||
_logger.LogWarning(errorMessage);
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
|
||||||
} else if (isInternalError) {
|
|
||||||
_logger.LogError(errorMessage);
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Critical);
|
|
||||||
} else {
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,26 +356,19 @@ public class ApprovalController : ControllerBase {
|
|||||||
} catch (ArgumentException ex) {
|
} catch (ArgumentException ex) {
|
||||||
isArgumentError = true;
|
isArgumentError = true;
|
||||||
errorMessage = ex.Message;
|
errorMessage = ex.Message;
|
||||||
|
_logger.LogWarning($"Argument error when attempting to get sub roles by sub role name: {errorMessage}");
|
||||||
return BadRequest(errorMessage);
|
return BadRequest(errorMessage);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
isInternalError = true;
|
isInternalError = true;
|
||||||
errorMessage = $"Cannot get role ID, because {ex.Message}";
|
errorMessage = $"Cannot get role ID, because {ex.Message}";
|
||||||
|
_logger.LogError(errorMessage);
|
||||||
return Problem(errorMessage);
|
return Problem(errorMessage);
|
||||||
} finally {
|
} finally {
|
||||||
string metricName = "GetSubRoleIdForSubRoleName";
|
string metricName = "GetSubRoleIdForSubRoleName";
|
||||||
DateTime end = DateTime.Now;
|
DateTime end = DateTime.Now;
|
||||||
double millisecondsDiff = (end - start).TotalMilliseconds;
|
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||||
_monInClient.PostAverage(metricName + "Latency", millisecondsDiff);
|
|
||||||
|
_monInUtils.PostMetrics(metricName, millisecondsDiff, isArgumentError, isInternalError);
|
||||||
if (isArgumentError) {
|
|
||||||
_logger.LogWarning(errorMessage);
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
|
||||||
} else if (isInternalError) {
|
|
||||||
_logger.LogError(errorMessage);
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Critical);
|
|
||||||
} else {
|
|
||||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -790,6 +790,42 @@ public class PCRBController : ControllerBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Route("pcrb/notify/approver")]
|
||||||
|
public async Task<IActionResult> NotifyApprover(PCRBNotification notification) {
|
||||||
|
DateTime start = DateTime.Now;
|
||||||
|
bool isArgumentError = false;
|
||||||
|
bool isInternalError = false;
|
||||||
|
string errorMessage = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
_logger.LogInformation("Attempting to notify an approver");
|
||||||
|
|
||||||
|
if (notification is null) throw new ArgumentNullException("notification cannot be null");
|
||||||
|
if (notification.PCRB is null) throw new ArgumentNullException("PCRB cannot be null");
|
||||||
|
if (notification.Approval is null) throw new ArgumentNullException("approval cannot be null");
|
||||||
|
if (string.IsNullOrWhiteSpace(notification.Message)) throw new ArgumentException("message cannot be null or empty");
|
||||||
|
|
||||||
|
await _pcrbService.NotifyApprover(notification);
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
} catch (ArgumentException ex) {
|
||||||
|
isArgumentError = true;
|
||||||
|
errorMessage = ex.Message;
|
||||||
|
return BadRequest(errorMessage);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
isInternalError = true;
|
||||||
|
errorMessage = $"Unable to notify an approver, because {ex.Message}";
|
||||||
|
return Problem(errorMessage);
|
||||||
|
} finally {
|
||||||
|
string metricName = "NotifyPCRBApprover";
|
||||||
|
DateTime end = DateTime.Now;
|
||||||
|
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||||
|
|
||||||
|
_monInUtils.PostMetrics(metricName, millisecondsDiff, isArgumentError, isInternalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("pcrb/notify/approvers")]
|
[Route("pcrb/notify/approvers")]
|
||||||
public async Task<IActionResult> NotifyApprovers(PCRBNotification notification) {
|
public async Task<IActionResult> NotifyApprovers(PCRBNotification notification) {
|
||||||
@ -937,7 +973,7 @@ public class PCRBController : ControllerBase {
|
|||||||
string errorMessage = "";
|
string errorMessage = "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
_logger.LogInformation($"Attempting to get attendees for plan# {planNumber}");
|
_logger.LogInformation($"Attempting to get follow ups for plan# {planNumber}");
|
||||||
|
|
||||||
if (planNumber <= 0) throw new ArgumentException($"{planNumber} is not a valid PCRB Plan#");
|
if (planNumber <= 0) throw new ArgumentException($"{planNumber} is not a valid PCRB Plan#");
|
||||||
|
|
||||||
@ -1026,4 +1062,136 @@ public class PCRBController : ControllerBase {
|
|||||||
_monInUtils.PostMetrics(metricName, millisecondsDiff, isArgumentError, isInternalError);
|
_monInUtils.PostMetrics(metricName, millisecondsDiff, isArgumentError, isInternalError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Route("pcrb/followUpComment")]
|
||||||
|
public async Task<IActionResult> CreateFollowUpComment(PCRBFollowUpComment comment) {
|
||||||
|
DateTime start = DateTime.Now;
|
||||||
|
bool isArgumentError = false;
|
||||||
|
bool isInternalError = false;
|
||||||
|
string errorMessage = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
_logger.LogInformation("Attempting to create follow up comment");
|
||||||
|
|
||||||
|
if (comment is null) throw new ArgumentNullException("comment cannot be null");
|
||||||
|
|
||||||
|
await _pcrbService.CreateFollowUpComment(comment);
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
} catch (ArgumentException ex) {
|
||||||
|
isArgumentError = true;
|
||||||
|
errorMessage = ex.Message;
|
||||||
|
return BadRequest(errorMessage);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
isInternalError = true;
|
||||||
|
errorMessage = $"Unable to create follow up comment, because {ex.Message}";
|
||||||
|
return Problem(errorMessage);
|
||||||
|
} finally {
|
||||||
|
string metricName = "CreatePCRBFollowUpComment";
|
||||||
|
DateTime end = DateTime.Now;
|
||||||
|
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||||
|
|
||||||
|
_monInUtils.PostMetrics(metricName, millisecondsDiff, isArgumentError, isInternalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
[Route("pcrb/followUpComments")]
|
||||||
|
public async Task<IActionResult> GetFollowUpCommentsByPlanNumber(int planNumber, bool bypassCache) {
|
||||||
|
DateTime start = DateTime.Now;
|
||||||
|
bool isArgumentError = false;
|
||||||
|
bool isInternalError = false;
|
||||||
|
string errorMessage = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
_logger.LogInformation($"Attempting to get follow up comments for plan# {planNumber}");
|
||||||
|
|
||||||
|
if (planNumber <= 0) throw new ArgumentException($"{planNumber} is not a valid PCRB Plan#");
|
||||||
|
|
||||||
|
List<PCRBFollowUpComment> comments = (await _pcrbService.GetFollowUpCommentsByPlanNumber(planNumber, bypassCache)).ToList();
|
||||||
|
|
||||||
|
return Ok(comments);
|
||||||
|
} catch (ArgumentException ex) {
|
||||||
|
isArgumentError = true;
|
||||||
|
errorMessage = ex.Message;
|
||||||
|
return BadRequest(errorMessage);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
isInternalError = true;
|
||||||
|
errorMessage = $"Cannot get follow up comments for plan# {planNumber}, because {ex.Message}";
|
||||||
|
return Problem(errorMessage);
|
||||||
|
} finally {
|
||||||
|
string metricName = "GetPCRBFollowUpComments";
|
||||||
|
DateTime end = DateTime.Now;
|
||||||
|
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||||
|
|
||||||
|
_monInUtils.PostMetrics(metricName, millisecondsDiff, isArgumentError, isInternalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut]
|
||||||
|
[Route("pcrb/followUpComment")]
|
||||||
|
public async Task<IActionResult> UpdateFollowUpComment(PCRBFollowUpComment comment) {
|
||||||
|
DateTime start = DateTime.Now;
|
||||||
|
bool isArgumentError = false;
|
||||||
|
bool isInternalError = false;
|
||||||
|
string errorMessage = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
_logger.LogInformation("Attempting to update follow up comment");
|
||||||
|
|
||||||
|
if (comment is null) throw new ArgumentNullException("comment cannot be null");
|
||||||
|
|
||||||
|
await _pcrbService.UpdateFollowUpComment(comment);
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
} catch (ArgumentException ex) {
|
||||||
|
isArgumentError = true;
|
||||||
|
errorMessage = ex.Message;
|
||||||
|
return BadRequest(errorMessage);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
isInternalError = true;
|
||||||
|
errorMessage = $"Unable to update follow up comment, because {ex.Message}";
|
||||||
|
return Problem(errorMessage);
|
||||||
|
} finally {
|
||||||
|
string metricName = "UpdatePCRBFollowUpComment";
|
||||||
|
DateTime end = DateTime.Now;
|
||||||
|
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||||
|
|
||||||
|
_monInUtils.PostMetrics(metricName, millisecondsDiff, isArgumentError, isInternalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete]
|
||||||
|
[Route("pcrb/followUpComment")]
|
||||||
|
public async Task<IActionResult> DeleteFollowUpComment(int id) {
|
||||||
|
DateTime start = DateTime.Now;
|
||||||
|
bool isArgumentError = false;
|
||||||
|
bool isInternalError = false;
|
||||||
|
string errorMessage = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
_logger.LogInformation("Attempting to delete follow up comment");
|
||||||
|
|
||||||
|
if (id <= 0) throw new ArgumentException($"{id} is not a valid PCRB follow up comment ID");
|
||||||
|
|
||||||
|
await _pcrbService.DeleteFollowUpComment(id);
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
} catch (ArgumentException ex) {
|
||||||
|
isArgumentError = true;
|
||||||
|
errorMessage = ex.Message;
|
||||||
|
return BadRequest(errorMessage);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
isInternalError = true;
|
||||||
|
errorMessage = $"Unable to delete follow up comment, because {ex.Message}";
|
||||||
|
return Problem(errorMessage);
|
||||||
|
} finally {
|
||||||
|
string metricName = "DeletePCRBFollowUpComment";
|
||||||
|
DateTime end = DateTime.Now;
|
||||||
|
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||||
|
|
||||||
|
_monInUtils.PostMetrics(metricName, millisecondsDiff, isArgumentError, isInternalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -13,6 +13,7 @@ public interface IApprovalService {
|
|||||||
Task<IEnumerable<User>> GetApprovalGroupMembers(int subRoleId);
|
Task<IEnumerable<User>> GetApprovalGroupMembers(int subRoleId);
|
||||||
Task CreateApproval(Approval approval);
|
Task CreateApproval(Approval approval);
|
||||||
Task UpdateApproval(Approval approval);
|
Task UpdateApproval(Approval approval);
|
||||||
|
Task DeleteApproval(int approvalID);
|
||||||
Task Approve(Approval approval);
|
Task Approve(Approval approval);
|
||||||
Task Deny(Approval approval);
|
Task Deny(Approval approval);
|
||||||
Task<IEnumerable<Approval>> GetApprovalsForIssueId(int issueId, bool bypassCache);
|
Task<IEnumerable<Approval>> GetApprovalsForIssueId(int issueId, bool bypassCache);
|
||||||
@ -40,12 +41,11 @@ public class ApprovalService : IApprovalService {
|
|||||||
|
|
||||||
StringBuilder queryBuilder = new();
|
StringBuilder queryBuilder = new();
|
||||||
queryBuilder.Append("insert into Approval (IssueID, RoleName, SubRole, UserID, SubRoleID, ItemStatus, ");
|
queryBuilder.Append("insert into Approval (IssueID, RoleName, SubRole, UserID, SubRoleID, ItemStatus, ");
|
||||||
queryBuilder.Append("AssignedDate, DocumentTypeID, DisplayDeniedDocument, Step, TaskID) ");
|
queryBuilder.Append("AssignedDate, DocumentTypeID, DisplayDeniedDocument, Step, TaskID, CompletedDate) ");
|
||||||
queryBuilder.Append($"values ({approval.IssueID}, '{approval.RoleName}', '{approval.SubRole}', {approval.UserID}, ");
|
queryBuilder.Append("values (@IssueID, @RoleName, @SubRole, @UserID, @SubRoleID, 0, @AssignedDate, 3, 0, @Step, ");
|
||||||
queryBuilder.Append($"{approval.SubRoleID}, 0, '{approval.AssignedDate.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
queryBuilder.Append("@TaskID, @CompletedDate)");
|
||||||
queryBuilder.Append($"3, 0, {approval.Step}, {approval.TaskID});");
|
|
||||||
|
|
||||||
int rowsCreated = await _dalService.ExecuteAsync(queryBuilder.ToString());
|
int rowsCreated = await _dalService.ExecuteAsync(queryBuilder.ToString(), approval);
|
||||||
|
|
||||||
if (rowsCreated <= 0) throw new Exception("Unable to insert approval in database");
|
if (rowsCreated <= 0) throw new Exception("Unable to insert approval in database");
|
||||||
|
|
||||||
@ -70,19 +70,16 @@ public class ApprovalService : IApprovalService {
|
|||||||
if (approvals is null || approvals.Count() == 0) {
|
if (approvals is null || approvals.Count() == 0) {
|
||||||
StringBuilder queryBuilder = new();
|
StringBuilder queryBuilder = new();
|
||||||
queryBuilder.Append("select a.*, src.SubRoleCategoryItem from Approval a ");
|
queryBuilder.Append("select a.*, src.SubRoleCategoryItem from Approval a ");
|
||||||
queryBuilder.Append("join SubRole sr on a.SubRoleID=sr.SubRoleID ");
|
queryBuilder.Append("left outer join SubRole sr on a.SubRoleID=sr.SubRoleID ");
|
||||||
queryBuilder.Append("join SubRoleCategory src on sr.SubRoleCategoryID=src.SubRoleCategoryID ");
|
queryBuilder.Append("left outer join SubRoleCategory src on sr.SubRoleCategoryID=src.SubRoleCategoryID ");
|
||||||
queryBuilder.Append($"where a.IssueID={issueId}");
|
queryBuilder.Append($"where a.IssueID={issueId}");
|
||||||
|
|
||||||
approvals = (await _dalService.QueryAsync<Approval>(queryBuilder.ToString())).ToList();
|
approvals = (await _dalService.QueryAsync<Approval>(queryBuilder.ToString())).ToList();
|
||||||
|
|
||||||
foreach (Approval approval in approvals) {
|
foreach (Approval approval in approvals) {
|
||||||
int successfulUpdates = 0;
|
|
||||||
|
|
||||||
User? user = await _userService.GetUserByUserId(approval.UserID);
|
User? user = await _userService.GetUserByUserId(approval.UserID);
|
||||||
if (user is not null) {
|
if (user is not null) {
|
||||||
approval.User = user;
|
approval.User = user;
|
||||||
successfulUpdates++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (approval.ItemStatus < 0)
|
if (approval.ItemStatus < 0)
|
||||||
@ -91,6 +88,9 @@ public class ApprovalService : IApprovalService {
|
|||||||
approval.StatusMessage = "Assigned";
|
approval.StatusMessage = "Assigned";
|
||||||
if (approval.ItemStatus > 0)
|
if (approval.ItemStatus > 0)
|
||||||
approval.StatusMessage = "Approved";
|
approval.StatusMessage = "Approved";
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(approval.SubRoleCategoryItem))
|
||||||
|
approval.SubRoleCategoryItem = approval.RoleName;
|
||||||
}
|
}
|
||||||
|
|
||||||
_cache.Set($"approvals{issueId}", approvals, DateTimeOffset.Now.AddMinutes(5));
|
_cache.Set($"approvals{issueId}", approvals, DateTimeOffset.Now.AddMinutes(5));
|
||||||
@ -217,8 +217,8 @@ public class ApprovalService : IApprovalService {
|
|||||||
if (approvals is null) {
|
if (approvals is null) {
|
||||||
StringBuilder queryBuilder = new();
|
StringBuilder queryBuilder = new();
|
||||||
queryBuilder.Append($"select a.*, src.SubRoleCategoryItem from Approval a ");
|
queryBuilder.Append($"select a.*, src.SubRoleCategoryItem from Approval a ");
|
||||||
queryBuilder.Append("join SubRole sr on a.SubRoleID=sr.SubRoleID ");
|
queryBuilder.Append("left outer join SubRole sr on a.SubRoleID=sr.SubRoleID ");
|
||||||
queryBuilder.Append("join SubRoleCategory src on sr.SubRoleCategoryID=src.SubRoleCategoryID ");
|
queryBuilder.Append("left outer join SubRoleCategory src on sr.SubRoleCategoryID=src.SubRoleCategoryID ");
|
||||||
queryBuilder.Append($"where UserID={userId} and ItemStatus=0 and ");
|
queryBuilder.Append($"where UserID={userId} and ItemStatus=0 and ");
|
||||||
queryBuilder.Append($"(AssignedDate is not null and ");
|
queryBuilder.Append($"(AssignedDate is not null and ");
|
||||||
queryBuilder.Append($"AssignedDate <= '{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}' and ");
|
queryBuilder.Append($"AssignedDate <= '{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}' and ");
|
||||||
@ -265,6 +265,23 @@ public class ApprovalService : IApprovalService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task DeleteApproval(int approvalID) {
|
||||||
|
try {
|
||||||
|
_logger.LogInformation($"Attempting to delete approval with ID: {approvalID}");
|
||||||
|
|
||||||
|
if (approvalID <= 0) throw new ArgumentException("Invalid approval ID");
|
||||||
|
|
||||||
|
string sql = "delete from Approval where ApprovalID=@ApprovalID";
|
||||||
|
|
||||||
|
int rowsDeleted = await _dalService.ExecuteAsync(sql, new { ApprovalID = approvalID });
|
||||||
|
|
||||||
|
if (rowsDeleted <= 0) throw new Exception("unable to delete approval from database");
|
||||||
|
} catch (Exception ex) {
|
||||||
|
_logger.LogError($"Unable to delete approval with ID: {approvalID}, because {ex.Message}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task Approve(Approval approval) {
|
public async Task Approve(Approval approval) {
|
||||||
try {
|
try {
|
||||||
_logger.LogInformation("Attempting to submit approval");
|
_logger.LogInformation("Attempting to submit approval");
|
||||||
|
@ -144,7 +144,7 @@ public class AuthenticationService : IAuthenticationService {
|
|||||||
Audience = _jwtAudience,
|
Audience = _jwtAudience,
|
||||||
Subject = identity,
|
Subject = identity,
|
||||||
NotBefore = DateTime.Now,
|
NotBefore = DateTime.Now,
|
||||||
Expires = DateTime.Now.AddHours(8),
|
Expires = DateTime.Now.AddDays(1),
|
||||||
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
|
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ public interface IPCRBService {
|
|||||||
Task UpdatePCR3Document(PCR3Document document);
|
Task UpdatePCR3Document(PCR3Document document);
|
||||||
Task<IEnumerable<PCR3Document>> GetPCR3DocumentsForPlanNumber(int planNumber, bool bypassCache);
|
Task<IEnumerable<PCR3Document>> GetPCR3DocumentsForPlanNumber(int planNumber, bool bypassCache);
|
||||||
Task NotifyNewApprovals(PCRB pcrb);
|
Task NotifyNewApprovals(PCRB pcrb);
|
||||||
|
Task NotifyApprover(PCRBNotification notification);
|
||||||
Task NotifyApprovers(PCRBNotification notification);
|
Task NotifyApprovers(PCRBNotification notification);
|
||||||
Task NotifyOriginator(PCRBNotification notification);
|
Task NotifyOriginator(PCRBNotification notification);
|
||||||
Task NotifyResponsiblePerson(PCRBActionItemNotification notification);
|
Task NotifyResponsiblePerson(PCRBActionItemNotification notification);
|
||||||
@ -41,6 +42,10 @@ public interface IPCRBService {
|
|||||||
Task<IEnumerable<PCRBFollowUp>> GetFollowUpsByPlanNumber(int planNumber, bool bypassCache);
|
Task<IEnumerable<PCRBFollowUp>> GetFollowUpsByPlanNumber(int planNumber, bool bypassCache);
|
||||||
Task UpdateFollowUp(PCRBFollowUp followUp);
|
Task UpdateFollowUp(PCRBFollowUp followUp);
|
||||||
Task DeleteFollowUp(int id);
|
Task DeleteFollowUp(int id);
|
||||||
|
Task CreateFollowUpComment(PCRBFollowUpComment comment);
|
||||||
|
Task<IEnumerable<PCRBFollowUpComment>> GetFollowUpCommentsByPlanNumber(int planNumber, bool bypassCache);
|
||||||
|
Task UpdateFollowUpComment(PCRBFollowUpComment comment);
|
||||||
|
Task DeleteFollowUpComment(int id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PCRBService : IPCRBService {
|
public class PCRBService : IPCRBService {
|
||||||
@ -110,6 +115,7 @@ public class PCRBService : IPCRBService {
|
|||||||
foreach (PCRB pcrb in allPCRBs) {
|
foreach (PCRB pcrb in allPCRBs) {
|
||||||
if (string.IsNullOrWhiteSpace(pcrb.OwnerName) && pcrb.OwnerID > 0)
|
if (string.IsNullOrWhiteSpace(pcrb.OwnerName) && pcrb.OwnerID > 0)
|
||||||
pcrb.OwnerName = (await _userService.GetUserByUserId(pcrb.OwnerID)).GetFullName();
|
pcrb.OwnerName = (await _userService.GetUserByUserId(pcrb.OwnerID)).GetFullName();
|
||||||
|
pcrb.FollowUps = await GetFollowUpsByPlanNumber(pcrb.PlanNumber, bypassCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
_cache.Set("allPCRBs", allPCRBs, DateTimeOffset.Now.AddHours(1));
|
_cache.Set("allPCRBs", allPCRBs, DateTimeOffset.Now.AddHours(1));
|
||||||
@ -144,6 +150,8 @@ public class PCRBService : IPCRBService {
|
|||||||
if (string.IsNullOrWhiteSpace(pcrb.OwnerName) && pcrb.OwnerID > 0)
|
if (string.IsNullOrWhiteSpace(pcrb.OwnerName) && pcrb.OwnerID > 0)
|
||||||
pcrb.OwnerName = (await _userService.GetUserByUserId(pcrb.OwnerID)).GetFullName();
|
pcrb.OwnerName = (await _userService.GetUserByUserId(pcrb.OwnerID)).GetFullName();
|
||||||
|
|
||||||
|
pcrb.FollowUps = await GetFollowUpsByPlanNumber(pcrb.PlanNumber, bypassCache);
|
||||||
|
|
||||||
_cache.Set($"pcrb{planNumber}", pcrb, DateTimeOffset.Now.AddHours(1));
|
_cache.Set($"pcrb{planNumber}", pcrb, DateTimeOffset.Now.AddHours(1));
|
||||||
_cache.Set($"pcrb{pcrb.Title}", pcrb, DateTimeOffset.Now.AddHours(1));
|
_cache.Set($"pcrb{pcrb.Title}", pcrb, DateTimeOffset.Now.AddHours(1));
|
||||||
}
|
}
|
||||||
@ -659,6 +667,62 @@ public class PCRBService : IPCRBService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task NotifyApprover(PCRBNotification notification) {
|
||||||
|
try {
|
||||||
|
_logger.LogInformation("Attempting to send a notification to an approver");
|
||||||
|
|
||||||
|
if (notification is null) throw new ArgumentNullException("notification cannot be null");
|
||||||
|
if (notification.PCRB is null) throw new ArgumentNullException("PCRB cannot be null");
|
||||||
|
if (notification.Approval is null) throw new ArgumentNullException("approval cannot be null");
|
||||||
|
|
||||||
|
User user = await _userService.GetUserByUserId(notification.Approval.UserID);
|
||||||
|
|
||||||
|
List<MailAddress> toAddresses = new();
|
||||||
|
toAddresses.Add(new MailAddress(user.Email));
|
||||||
|
|
||||||
|
List<string> ccEmails = new List<string>();
|
||||||
|
|
||||||
|
if (notification.NotifyQaPreApprover) {
|
||||||
|
IEnumerable<User> qaPreApprovers = await GetQAPreApprovers();
|
||||||
|
|
||||||
|
foreach (User qaPreApprover in qaPreApprovers) {
|
||||||
|
if (!ccEmails.Contains(qaPreApprover.Email))
|
||||||
|
ccEmails.Add(qaPreApprover.Email);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MailAddress> ccAddresses = new();
|
||||||
|
foreach (string email in ccEmails) {
|
||||||
|
ccAddresses.Add(new MailAddress(email));
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder sb = new();
|
||||||
|
|
||||||
|
string subject = string.Empty;
|
||||||
|
if (!string.IsNullOrWhiteSpace(notification.Subject)) {
|
||||||
|
subject = notification.Subject;
|
||||||
|
} else {
|
||||||
|
sb.Append($"[Approval Update] Mesa Fab Approval - PCRB# {notification.PCRB.PlanNumber} - ");
|
||||||
|
sb.Append($"{notification.PCRB.Title}");
|
||||||
|
|
||||||
|
subject = sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Clear();
|
||||||
|
sb.Append($"{notification.Message} <br /> <br />");
|
||||||
|
sb.Append($"Click {_siteBaseUrl}/redirect?redirectPath=pcrb/{notification.PCRB.PlanNumber} ");
|
||||||
|
sb.Append("to view the PCRB.");
|
||||||
|
|
||||||
|
await _smtpService.SendEmail(toAddresses, ccAddresses, subject, sb.ToString());
|
||||||
|
|
||||||
|
notification.Approval.NotifyDate = DateTime.Now;
|
||||||
|
await _approvalService.UpdateApproval(notification.Approval);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
_logger.LogError($"Unable to send notification to approver, because {ex.Message}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task NotifyApprovers(PCRBNotification notification) {
|
public async Task NotifyApprovers(PCRBNotification notification) {
|
||||||
try {
|
try {
|
||||||
_logger.LogInformation("Attempting to send notification to approvers");
|
_logger.LogInformation("Attempting to send notification to approvers");
|
||||||
@ -712,9 +776,28 @@ public class PCRBService : IPCRBService {
|
|||||||
List<MailAddress> toAddresses = new();
|
List<MailAddress> toAddresses = new();
|
||||||
toAddresses.Add(new MailAddress(user.Email));
|
toAddresses.Add(new MailAddress(user.Email));
|
||||||
|
|
||||||
List<MailAddress> ccAddresses = new();
|
List<string> ccEmails = new List<string>();
|
||||||
|
|
||||||
string subject = $"[Update] Mesa Fab Approval - PCRB# {notification.PCRB.PlanNumber} - {notification.PCRB.Title}";
|
if (notification.NotifyQaPreApprover) {
|
||||||
|
IEnumerable<User> qaPreApprovers = await GetQAPreApprovers();
|
||||||
|
|
||||||
|
foreach (User qaPreApprover in qaPreApprovers) {
|
||||||
|
if (!ccEmails.Contains(qaPreApprover.Email))
|
||||||
|
ccEmails.Add(qaPreApprover.Email);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MailAddress> ccAddresses = new();
|
||||||
|
foreach (string email in ccEmails) {
|
||||||
|
ccAddresses.Add(new MailAddress(email));
|
||||||
|
}
|
||||||
|
|
||||||
|
string subject = string.Empty;
|
||||||
|
if (!string.IsNullOrWhiteSpace(notification.Subject)) {
|
||||||
|
subject = notification.Subject;
|
||||||
|
} else {
|
||||||
|
subject = $"[Update] Mesa Fab Approval - PCRB# {notification.PCRB.PlanNumber} - {notification.PCRB.Title}";
|
||||||
|
}
|
||||||
|
|
||||||
StringBuilder bodyBuilder = new();
|
StringBuilder bodyBuilder = new();
|
||||||
bodyBuilder.Append($"{notification.Message} <br /> <br />");
|
bodyBuilder.Append($"{notification.Message} <br /> <br />");
|
||||||
@ -763,8 +846,8 @@ public class PCRBService : IPCRBService {
|
|||||||
if (followUp is null) throw new ArgumentNullException("follow up cannot be null");
|
if (followUp is null) throw new ArgumentNullException("follow up cannot be null");
|
||||||
|
|
||||||
StringBuilder queryBuilder = new();
|
StringBuilder queryBuilder = new();
|
||||||
queryBuilder.Append("insert into CCPCRBFollowUp (PlanNumber, Step, FollowUpDate, CompletedDate) ");
|
queryBuilder.Append("insert into CCPCRBFollowUp (PlanNumber, Step, FollowUpDate, CompletedDate, UpdateDate) ");
|
||||||
queryBuilder.Append("values (@PlanNumber, @Step, @FollowUpDate, @CompletedDate)");
|
queryBuilder.Append("values (@PlanNumber, @Step, @FollowUpDate, @CompletedDate, @UpdateDate)");
|
||||||
|
|
||||||
int rowsReturned = await _dalService.ExecuteAsync<PCRBFollowUp>(queryBuilder.ToString(), followUp);
|
int rowsReturned = await _dalService.ExecuteAsync<PCRBFollowUp>(queryBuilder.ToString(), followUp);
|
||||||
|
|
||||||
@ -792,7 +875,7 @@ public class PCRBService : IPCRBService {
|
|||||||
followUps = await _dalService.QueryAsync<PCRBFollowUp>(sql, new { PlanNumber = planNumber });
|
followUps = await _dalService.QueryAsync<PCRBFollowUp>(sql, new { PlanNumber = planNumber });
|
||||||
|
|
||||||
if (followUps is not null)
|
if (followUps is not null)
|
||||||
_cache.Set($"pcrbFollowUps{planNumber}", followUps, DateTimeOffset.Now.AddMinutes(15));
|
_cache.Set($"pcrbFollowUps{planNumber}", followUps, DateTimeOffset.Now.AddHours(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
return followUps ?? new List<PCRBFollowUp>();
|
return followUps ?? new List<PCRBFollowUp>();
|
||||||
@ -811,7 +894,8 @@ public class PCRBService : IPCRBService {
|
|||||||
|
|
||||||
StringBuilder queryBuilder = new();
|
StringBuilder queryBuilder = new();
|
||||||
queryBuilder.Append("update CCPCRBFollowUp set Step=@Step, FollowUpDate=@FollowUpDate, IsComplete=@IsComplete, ");
|
queryBuilder.Append("update CCPCRBFollowUp set Step=@Step, FollowUpDate=@FollowUpDate, IsComplete=@IsComplete, ");
|
||||||
queryBuilder.Append("IsDeleted=@IsDeleted, CompletedDate=@CompletedDate, Comments=@Comments ");
|
queryBuilder.Append("IsDeleted=@IsDeleted, CompletedDate=@CompletedDate, IsPendingApproval=@IsPendingApproval, ");
|
||||||
|
queryBuilder.Append("UpdateDate=@UpdateDate ");
|
||||||
queryBuilder.Append("where ID=@ID");
|
queryBuilder.Append("where ID=@ID");
|
||||||
|
|
||||||
int rowsAffected = await _dalService.ExecuteAsync<PCRBFollowUp>(queryBuilder.ToString(), followUp);
|
int rowsAffected = await _dalService.ExecuteAsync<PCRBFollowUp>(queryBuilder.ToString(), followUp);
|
||||||
@ -840,6 +924,89 @@ public class PCRBService : IPCRBService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task CreateFollowUpComment(PCRBFollowUpComment comment) {
|
||||||
|
try {
|
||||||
|
_logger.LogInformation("Attempting to create PCRB follow up");
|
||||||
|
|
||||||
|
if (comment is null) throw new ArgumentNullException("comment cannot be null");
|
||||||
|
|
||||||
|
StringBuilder queryBuilder = new();
|
||||||
|
queryBuilder.Append("insert into CCPCRBFollowUpComments (PlanNumber, FollowUpID, Comment, CommentDate, UserID) ");
|
||||||
|
queryBuilder.Append("values (@PlanNumber, @FollowUpID, @Comment, @CommentDate, @UserID)");
|
||||||
|
|
||||||
|
int rowsReturned = await _dalService.ExecuteAsync<PCRBFollowUpComment>(queryBuilder.ToString(), comment);
|
||||||
|
|
||||||
|
if (rowsReturned <= 0) throw new Exception("unable to insert new follow up comment in the database");
|
||||||
|
} catch (Exception ex) {
|
||||||
|
_logger.LogError($"Unable to create new follow up comment, because {ex.Message}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<PCRBFollowUpComment>> GetFollowUpCommentsByPlanNumber(int planNumber, bool bypassCache) {
|
||||||
|
try {
|
||||||
|
_logger.LogInformation($"Attempting to fetch follow up comments for PCRB {planNumber}");
|
||||||
|
|
||||||
|
if (planNumber <= 0) throw new ArgumentException($"{planNumber} is not a valid PCRB Plan#");
|
||||||
|
|
||||||
|
IEnumerable<PCRBFollowUpComment>? comments = new List<PCRBFollowUpComment>();
|
||||||
|
|
||||||
|
if (!bypassCache)
|
||||||
|
comments = _cache.Get<IEnumerable<PCRBFollowUpComment>>($"pcrbFollowUpComments{planNumber}");
|
||||||
|
|
||||||
|
if (comments is null || comments.Count() == 0) {
|
||||||
|
string sql = "select * from CCPCRBFollowUpComments where PlanNumber=@PlanNumber";
|
||||||
|
|
||||||
|
comments = await _dalService.QueryAsync<PCRBFollowUpComment>(sql, new { PlanNumber = planNumber });
|
||||||
|
|
||||||
|
if (comments is not null)
|
||||||
|
_cache.Set($"pcrbFollowUpComments{planNumber}", comments, DateTimeOffset.Now.AddHours(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return comments ?? new List<PCRBFollowUpComment>();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
_logger.LogError($"Unable to fetch follow up comments for PCRB {planNumber}, because {ex.Message}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpdateFollowUpComment(PCRBFollowUpComment comment) {
|
||||||
|
try {
|
||||||
|
_logger.LogInformation("Attempting to update a follow up");
|
||||||
|
|
||||||
|
if (comment is null)
|
||||||
|
throw new ArgumentNullException("comment cannot be null");
|
||||||
|
|
||||||
|
StringBuilder queryBuilder = new();
|
||||||
|
queryBuilder.Append("update CCPCRBFollowUpComments set Comment=@Comment, CommentDate=@CommentDate, ");
|
||||||
|
queryBuilder.Append("UserID=@UserID where ID=@ID");
|
||||||
|
|
||||||
|
int rowsAffected = await _dalService.ExecuteAsync<PCRBFollowUpComment>(queryBuilder.ToString(), comment);
|
||||||
|
|
||||||
|
if (rowsAffected <= 0) throw new Exception("update failed in database");
|
||||||
|
} catch (Exception ex) {
|
||||||
|
_logger.LogError($"Unable to update follow up comment, because {ex.Message}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteFollowUpComment(int id) {
|
||||||
|
try {
|
||||||
|
_logger.LogInformation($"Attempting to delete follow up comment {id}");
|
||||||
|
|
||||||
|
if (id <= 0) throw new ArgumentException($"{id} is not a valid follow up ID");
|
||||||
|
|
||||||
|
string sql = "delete from CCPCRBFollowUpComments where ID=@ID";
|
||||||
|
|
||||||
|
int rowsAffected = await _dalService.ExecuteAsync(sql, new { ID = id });
|
||||||
|
|
||||||
|
if (rowsAffected <= 0) throw new Exception("delete operation failed in database");
|
||||||
|
} catch (Exception ex) {
|
||||||
|
_logger.LogError($"Unable to delete follow up comment {id}, because {ex.Message}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task SaveAttachmentInDb(IFormFile file, PCRBAttachment attachment) {
|
private async Task SaveAttachmentInDb(IFormFile file, PCRBAttachment attachment) {
|
||||||
try {
|
try {
|
||||||
_logger.LogInformation($"Attempting to save attachment to database");
|
_logger.LogInformation($"Attempting to save attachment to database");
|
||||||
@ -863,4 +1030,34 @@ public class PCRBService : IPCRBService {
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<IEnumerable<User>> GetQAPreApprovers() {
|
||||||
|
try {
|
||||||
|
_logger.LogInformation("Attempting to fetch QA Pre-Approvers");
|
||||||
|
|
||||||
|
IEnumerable<User> qaPreApprovers = new List<User>();
|
||||||
|
|
||||||
|
int qaPreApproverRoleId = await _approvalService.GetRoleIdForRoleName("QA_PRE_APPROVAL");
|
||||||
|
|
||||||
|
if (qaPreApproverRoleId > 0) {
|
||||||
|
IEnumerable<SubRole> qaPreApproverSubRoles =
|
||||||
|
await _approvalService.GetSubRolesForSubRoleName("QA_PRE_APPROVAL", qaPreApproverRoleId);
|
||||||
|
|
||||||
|
foreach (SubRole subRole in qaPreApproverSubRoles) {
|
||||||
|
IEnumerable<User> members =
|
||||||
|
await _approvalService.GetApprovalGroupMembers(subRole.SubRoleID);
|
||||||
|
|
||||||
|
foreach (User member in members) {
|
||||||
|
if (!qaPreApprovers.Any(u => u.UserID == member.UserID))
|
||||||
|
qaPreApprovers = qaPreApprovers.Append(member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return qaPreApprovers;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
_logger.LogError($"Unable to fetch QA Pre-Approvers, because {ex.Message}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
95
MesaFabApproval.Client.Test/ApprovalServiceTests.cs
Normal file
95
MesaFabApproval.Client.Test/ApprovalServiceTests.cs
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using MesaFabApproval.Client.Services;
|
||||||
|
using MesaFabApproval.Shared.Models;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
|
||||||
|
using Moq;
|
||||||
|
using Moq.Protected;
|
||||||
|
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace MesaFabApproval.Client.Test;
|
||||||
|
|
||||||
|
public class ApprovalServiceTests {
|
||||||
|
private readonly Mock<IMemoryCache> _cacheMock;
|
||||||
|
private readonly Mock<IHttpClientFactory> _httpClientFactoryMock;
|
||||||
|
private readonly ApprovalService _approvalService;
|
||||||
|
|
||||||
|
public ApprovalServiceTests() {
|
||||||
|
_cacheMock = new Mock<IMemoryCache>();
|
||||||
|
_httpClientFactoryMock = new Mock<IHttpClientFactory>();
|
||||||
|
_approvalService = new ApprovalService(_cacheMock.Object, _httpClientFactoryMock.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteApproval_ValidApprovalID_DeletesApproval() {
|
||||||
|
int approvalID = 1;
|
||||||
|
|
||||||
|
Mock<HttpMessageHandler> handlerMock = new Mock<HttpMessageHandler>();
|
||||||
|
|
||||||
|
handlerMock
|
||||||
|
.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(req => req.Method == HttpMethod.Delete),
|
||||||
|
ItExpr.IsAny<CancellationToken>()
|
||||||
|
)
|
||||||
|
.ReturnsAsync(new HttpResponseMessage {
|
||||||
|
StatusCode = HttpStatusCode.OK,
|
||||||
|
});
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(handlerMock.Object) {
|
||||||
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
|
};
|
||||||
|
|
||||||
|
_httpClientFactoryMock.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
|
await _approvalService.DeleteApproval(approvalID);
|
||||||
|
|
||||||
|
handlerMock.Protected().Verify(
|
||||||
|
"SendAsync",
|
||||||
|
Times.Once(),
|
||||||
|
ItExpr.Is<HttpRequestMessage>(req => req.Method == HttpMethod.Delete),
|
||||||
|
ItExpr.IsAny<CancellationToken>()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteApproval_InvalidApprovalID_ThrowsArgumentException() {
|
||||||
|
int approvalID = 0;
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<ArgumentException>(() => _approvalService.DeleteApproval(approvalID));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteApproval_DeletionFails_ThrowsException() {
|
||||||
|
int approvalID = 1;
|
||||||
|
|
||||||
|
Mock<HttpMessageHandler> handlerMock = new Mock<HttpMessageHandler>();
|
||||||
|
handlerMock
|
||||||
|
.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(req => req.Method == HttpMethod.Delete),
|
||||||
|
ItExpr.IsAny<CancellationToken>()
|
||||||
|
)
|
||||||
|
.ReturnsAsync(new HttpResponseMessage {
|
||||||
|
StatusCode = HttpStatusCode.BadRequest,
|
||||||
|
ReasonPhrase = "Bad Request"
|
||||||
|
});
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(handlerMock.Object) {
|
||||||
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
|
};
|
||||||
|
|
||||||
|
_httpClientFactoryMock.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _approvalService.DeleteApproval(approvalID));
|
||||||
|
}
|
||||||
|
}
|
18
MesaFabApproval.Client.Test/MockMemoryCacheService.cs
Normal file
18
MesaFabApproval.Client.Test/MockMemoryCacheService.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
|
||||||
|
using Moq;
|
||||||
|
|
||||||
|
namespace MesaFabApproval.Client.Test;
|
||||||
|
|
||||||
|
public static class MockMemoryCacheService {
|
||||||
|
public static Mock<IMemoryCache> GetMemoryCache(object expectedValue) {
|
||||||
|
Mock<IMemoryCache> mockMemoryCache = new Mock<IMemoryCache>();
|
||||||
|
mockMemoryCache
|
||||||
|
.Setup(x => x.TryGetValue(It.IsAny<object>(), out expectedValue))
|
||||||
|
.Returns(true);
|
||||||
|
mockMemoryCache
|
||||||
|
.Setup(x => x.CreateEntry(It.IsAny<object>()))
|
||||||
|
.Returns(Mock.Of<ICacheEntry>());
|
||||||
|
return mockMemoryCache;
|
||||||
|
}
|
||||||
|
}
|
320
MesaFabApproval.Client.Test/PCRBFollowUpCommentTests.cs
Normal file
320
MesaFabApproval.Client.Test/PCRBFollowUpCommentTests.cs
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
using System.Net;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
using MesaFabApproval.Client.Services;
|
||||||
|
using MesaFabApproval.Shared.Models;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
|
||||||
|
using Moq;
|
||||||
|
using Moq.Protected;
|
||||||
|
|
||||||
|
using MudBlazor;
|
||||||
|
|
||||||
|
namespace MesaFabApproval.Client.Test;
|
||||||
|
|
||||||
|
public class PCRBFollowUpCommentTests {
|
||||||
|
private readonly Mock<IMemoryCache> _mockCache;
|
||||||
|
private readonly Mock<IHttpClientFactory> _mockHttpClientFactory;
|
||||||
|
private readonly Mock<ISnackbar> _mockSnackbar;
|
||||||
|
private readonly Mock<IUserService> _mockUserService;
|
||||||
|
private readonly PCRBService _pcrbService;
|
||||||
|
|
||||||
|
private static PCRBFollowUpComment FOLLOW_UP_COMMENT = new PCRBFollowUpComment {
|
||||||
|
ID = 1,
|
||||||
|
PlanNumber = 123,
|
||||||
|
FollowUpID = 1,
|
||||||
|
Comment = "Test Comment",
|
||||||
|
UserID = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
private static HttpResponseMessage GET_RESPONSE = new HttpResponseMessage {
|
||||||
|
StatusCode = HttpStatusCode.OK,
|
||||||
|
Content = new StringContent(JsonSerializer.Serialize(new List<PCRBFollowUpComment> { FOLLOW_UP_COMMENT }))
|
||||||
|
};
|
||||||
|
|
||||||
|
private static IEnumerable<PCRBFollowUpComment> FOLLOW_UPS_COMMENTS = new List<PCRBFollowUpComment>() { FOLLOW_UP_COMMENT };
|
||||||
|
|
||||||
|
private static HttpResponseMessage SUCCESSFUL_RESPONSE = new HttpResponseMessage(HttpStatusCode.OK);
|
||||||
|
private static HttpResponseMessage UNSUCCESSFUL_RESPONSE = new HttpResponseMessage(HttpStatusCode.InternalServerError);
|
||||||
|
|
||||||
|
public PCRBFollowUpCommentTests() {
|
||||||
|
_mockCache = MockMemoryCacheService.GetMemoryCache(FOLLOW_UPS_COMMENTS);
|
||||||
|
_mockHttpClientFactory = new Mock<IHttpClientFactory>();
|
||||||
|
_mockSnackbar = new Mock<ISnackbar>();
|
||||||
|
_mockUserService = new Mock<IUserService>();
|
||||||
|
|
||||||
|
_pcrbService = new PCRBService(
|
||||||
|
_mockCache.Object,
|
||||||
|
_mockHttpClientFactory.Object,
|
||||||
|
_mockSnackbar.Object,
|
||||||
|
_mockUserService.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateFollowUpComment_WithValidParams_ShouldCallHttpPost_AndRefreshCache() {
|
||||||
|
Mock<HttpMessageHandler> mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Post),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(SUCCESSFUL_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Get),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(GET_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
||||||
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
|
};
|
||||||
|
|
||||||
|
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
|
await _pcrbService.CreateFollowUpComment(FOLLOW_UP_COMMENT);
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected().Verify(
|
||||||
|
"SendAsync",
|
||||||
|
Times.Once(),
|
||||||
|
ItExpr.Is<HttpRequestMessage>(
|
||||||
|
req =>
|
||||||
|
req.Method == HttpMethod.Post &&
|
||||||
|
req.RequestUri != null &&
|
||||||
|
req.RequestUri.AbsoluteUri.Equals("https://localhost:5000/pcrb/followUpComment")),
|
||||||
|
ItExpr.IsAny<CancellationToken>());
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected().Verify(
|
||||||
|
"SendAsync",
|
||||||
|
Times.Once(),
|
||||||
|
ItExpr.Is<HttpRequestMessage>(
|
||||||
|
req =>
|
||||||
|
req.Method == HttpMethod.Get &&
|
||||||
|
req.RequestUri != null &&
|
||||||
|
req.RequestUri.AbsoluteUri.Equals("https://localhost:5000/pcrb/followUpComments?planNumber=123&bypassCache=True")),
|
||||||
|
ItExpr.IsAny<CancellationToken>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateFollowUpComment_WithBadResponse_ShouldThrowException() {
|
||||||
|
Mock<HttpMessageHandler> mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Post),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(UNSUCCESSFUL_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
||||||
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
|
};
|
||||||
|
|
||||||
|
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.CreateFollowUpComment(FOLLOW_UP_COMMENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateFollowUpComment_WithNullParam_ShouldThrowException() {
|
||||||
|
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.CreateFollowUpComment(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetFollowUpCommentsByPlanNumber_WithBypassCache_ShouldCallHttpGetAndReturnFollowUps() {
|
||||||
|
Mock<HttpMessageHandler> mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Get),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(GET_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
||||||
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
|
};
|
||||||
|
|
||||||
|
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
|
IEnumerable<PCRBFollowUpComment> comments = await _pcrbService.GetFollowUpCommentsByPlanNumber(123, true);
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected().Verify(
|
||||||
|
"SendAsync",
|
||||||
|
Times.Once(),
|
||||||
|
ItExpr.Is<HttpRequestMessage>(
|
||||||
|
req =>
|
||||||
|
req.Method == HttpMethod.Get &&
|
||||||
|
req.RequestUri != null &&
|
||||||
|
req.RequestUri.AbsoluteUri.Equals("https://localhost:5000/pcrb/followUpComments?planNumber=123&bypassCache=True")),
|
||||||
|
ItExpr.IsAny<CancellationToken>());
|
||||||
|
|
||||||
|
Assert.Single(comments);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetFollowUpCommentsByPlanNumber_WithoutBypassCache_ShouldReturnFollowUpsFromCache() {
|
||||||
|
IEnumerable<PCRBFollowUpComment> comments = await _pcrbService.GetFollowUpCommentsByPlanNumber(1, false);
|
||||||
|
Assert.Single(comments);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetFollowUpCommentsByPlanNumber_WithBadResponse_ShouldThrowException() {
|
||||||
|
Mock<HttpMessageHandler> mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Get),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(UNSUCCESSFUL_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
||||||
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
|
};
|
||||||
|
|
||||||
|
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.GetFollowUpCommentsByPlanNumber(1, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateFollowUpComment_WithValidParams_ShouldCallHttpPut() {
|
||||||
|
Mock<HttpMessageHandler> mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Put),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(SUCCESSFUL_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Get),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(GET_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
||||||
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
|
};
|
||||||
|
|
||||||
|
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
|
await _pcrbService.UpdateFollowUpComment(FOLLOW_UP_COMMENT);
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected().Verify(
|
||||||
|
"SendAsync",
|
||||||
|
Times.Once(),
|
||||||
|
ItExpr.Is<HttpRequestMessage>(
|
||||||
|
req =>
|
||||||
|
req.Method == HttpMethod.Put &&
|
||||||
|
req.RequestUri != null &&
|
||||||
|
req.RequestUri.AbsoluteUri.Equals("https://localhost:5000/pcrb/followUpComment")),
|
||||||
|
ItExpr.IsAny<CancellationToken>());
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected().Verify(
|
||||||
|
"SendAsync",
|
||||||
|
Times.Once(),
|
||||||
|
ItExpr.Is<HttpRequestMessage>(
|
||||||
|
req =>
|
||||||
|
req.Method == HttpMethod.Get &&
|
||||||
|
req.RequestUri != null &&
|
||||||
|
req.RequestUri.AbsoluteUri.Equals("https://localhost:5000/pcrb/followUpComments?planNumber=123&bypassCache=True")),
|
||||||
|
ItExpr.IsAny<CancellationToken>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateFollowUpComment_WithNullParam_ShouldThrowException() {
|
||||||
|
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.UpdateFollowUpComment(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateFollowUpComment_WithBadResponse_ShouldThrowException() {
|
||||||
|
Mock<HttpMessageHandler> mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Put),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(UNSUCCESSFUL_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
||||||
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
|
};
|
||||||
|
|
||||||
|
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.UpdateFollowUpComment(FOLLOW_UP_COMMENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteFollowUpComment_WithValidParams_ShouldCallHttpDelete() {
|
||||||
|
Mock<HttpMessageHandler> mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Delete),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(SUCCESSFUL_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
||||||
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
|
};
|
||||||
|
|
||||||
|
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
|
await _pcrbService.DeleteFollowUpComment(1);
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected().Verify(
|
||||||
|
"SendAsync",
|
||||||
|
Times.Once(),
|
||||||
|
ItExpr.Is<HttpRequestMessage>(
|
||||||
|
req =>
|
||||||
|
req.Method == HttpMethod.Delete &&
|
||||||
|
req.RequestUri != null &&
|
||||||
|
req.RequestUri.AbsoluteUri.Equals("https://localhost:5000/pcrb/followUpComment?id=1")),
|
||||||
|
ItExpr.IsAny<CancellationToken>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteFollowUpComment_WithBadId_ShouldThrowException() {
|
||||||
|
await Assert.ThrowsAsync<ArgumentException>(() => _pcrbService.DeleteFollowUpComment(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteFollowUpComment_WithBadResponse_ShouldThrowException() {
|
||||||
|
Mock<HttpMessageHandler> mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Delete),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(UNSUCCESSFUL_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
||||||
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
|
};
|
||||||
|
|
||||||
|
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.DeleteFollowUpComment(1));
|
||||||
|
}
|
||||||
|
}
|
321
MesaFabApproval.Client.Test/PCRBFollowUpTests.cs
Normal file
321
MesaFabApproval.Client.Test/PCRBFollowUpTests.cs
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
using System.Net;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
using MesaFabApproval.Client.Services;
|
||||||
|
using MesaFabApproval.Shared.Models;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
|
||||||
|
using Moq;
|
||||||
|
using Moq.Protected;
|
||||||
|
|
||||||
|
using MudBlazor;
|
||||||
|
|
||||||
|
namespace MesaFabApproval.Client.Test;
|
||||||
|
|
||||||
|
public partial class PCRBFollowUpTests {
|
||||||
|
private readonly Mock<IMemoryCache> _mockCache;
|
||||||
|
private readonly Mock<IHttpClientFactory> _mockHttpClientFactory;
|
||||||
|
private readonly Mock<ISnackbar> _mockSnackbar;
|
||||||
|
private readonly Mock<IUserService> _mockUserService;
|
||||||
|
private readonly PCRBService _pcrbService;
|
||||||
|
|
||||||
|
private static PCRBFollowUp FOLLOW_UP = new PCRBFollowUp {
|
||||||
|
ID = 1,
|
||||||
|
PlanNumber = 123,
|
||||||
|
Step = 1,
|
||||||
|
FollowUpDate = DateTime.Now
|
||||||
|
};
|
||||||
|
|
||||||
|
private static HttpResponseMessage GET_RESPONSE = new HttpResponseMessage {
|
||||||
|
StatusCode = HttpStatusCode.OK,
|
||||||
|
Content = new StringContent(JsonSerializer.Serialize(new List<PCRBFollowUp> { FOLLOW_UP }))
|
||||||
|
};
|
||||||
|
|
||||||
|
private static IEnumerable<PCRBFollowUp> FOLLOW_UPS = new List<PCRBFollowUp>() {
|
||||||
|
new PCRBFollowUp { ID = 1, PlanNumber = 1, Step = 1, FollowUpDate = DateTime.Now }
|
||||||
|
};
|
||||||
|
|
||||||
|
private static HttpResponseMessage SUCCESSFUL_RESPONSE = new HttpResponseMessage(HttpStatusCode.OK);
|
||||||
|
private static HttpResponseMessage UNSUCCESSFUL_RESPONSE = new HttpResponseMessage(HttpStatusCode.InternalServerError);
|
||||||
|
|
||||||
|
public PCRBFollowUpTests() {
|
||||||
|
_mockCache = MockMemoryCacheService.GetMemoryCache(FOLLOW_UPS);
|
||||||
|
_mockHttpClientFactory = new Mock<IHttpClientFactory>();
|
||||||
|
_mockSnackbar = new Mock<ISnackbar>();
|
||||||
|
_mockUserService = new Mock<IUserService>();
|
||||||
|
|
||||||
|
_pcrbService = new PCRBService(
|
||||||
|
_mockCache.Object,
|
||||||
|
_mockHttpClientFactory.Object,
|
||||||
|
_mockSnackbar.Object,
|
||||||
|
_mockUserService.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateFollowUp_WithValidParams_ShouldCallHttpPost_AndRefreshCache() {
|
||||||
|
Mock<HttpMessageHandler> mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Post),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(SUCCESSFUL_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Get),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(GET_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
||||||
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
|
};
|
||||||
|
|
||||||
|
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
|
await _pcrbService.CreateFollowUp(FOLLOW_UP);
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected().Verify(
|
||||||
|
"SendAsync",
|
||||||
|
Times.Once(),
|
||||||
|
ItExpr.Is<HttpRequestMessage>(
|
||||||
|
req =>
|
||||||
|
req.Method == HttpMethod.Post &&
|
||||||
|
req.RequestUri != null &&
|
||||||
|
req.RequestUri.AbsoluteUri.Equals("https://localhost:5000/pcrb/followUp")),
|
||||||
|
ItExpr.IsAny<CancellationToken>());
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected().Verify(
|
||||||
|
"SendAsync",
|
||||||
|
Times.Once(),
|
||||||
|
ItExpr.Is<HttpRequestMessage>(
|
||||||
|
req =>
|
||||||
|
req.Method == HttpMethod.Get &&
|
||||||
|
req.RequestUri != null &&
|
||||||
|
req.RequestUri.AbsoluteUri.Equals("https://localhost:5000/pcrb/followUps?planNumber=123&bypassCache=True")),
|
||||||
|
ItExpr.IsAny<CancellationToken>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateFollowUp_WithBadResponse_ShouldThrowException() {
|
||||||
|
Mock<HttpMessageHandler> mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Post),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(UNSUCCESSFUL_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
||||||
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
|
};
|
||||||
|
|
||||||
|
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.CreateFollowUp(FOLLOW_UP));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateFollowUp_WithNullParam_ShouldThrowException() {
|
||||||
|
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.CreateFollowUp(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetFollowUpsByPlanNumber_WithBypassCache_ShouldCallHttpGetAndReturnFollowUps() {
|
||||||
|
Mock<HttpMessageHandler> mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Get),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(GET_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
||||||
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
|
};
|
||||||
|
|
||||||
|
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
|
IEnumerable<PCRBFollowUp> followUps = await _pcrbService.GetFollowUpsByPlanNumber(123, true);
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected().Verify(
|
||||||
|
"SendAsync",
|
||||||
|
Times.Once(),
|
||||||
|
ItExpr.Is<HttpRequestMessage>(
|
||||||
|
req =>
|
||||||
|
req.Method == HttpMethod.Get &&
|
||||||
|
req.RequestUri != null &&
|
||||||
|
req.RequestUri.AbsoluteUri.Equals("https://localhost:5000/pcrb/followUps?planNumber=123&bypassCache=True")),
|
||||||
|
ItExpr.IsAny<CancellationToken>());
|
||||||
|
|
||||||
|
Assert.Single(followUps);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetFollowUpsByPlanNumber_WithoutBypassCache_ShouldReturnFollowUpsFromCache() {
|
||||||
|
IEnumerable<PCRBFollowUp> followUps = await _pcrbService.GetFollowUpsByPlanNumber(1, false);
|
||||||
|
Assert.Single(followUps);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetFollowUpsByPlanNumber_WithBadResponse_ShouldThrowException() {
|
||||||
|
Mock<HttpMessageHandler> mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Get),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(UNSUCCESSFUL_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
||||||
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
|
};
|
||||||
|
|
||||||
|
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.GetFollowUpsByPlanNumber(1, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateFollowUp_WithValidParams_ShouldCallHttpPut() {
|
||||||
|
Mock<HttpMessageHandler> mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Put),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(SUCCESSFUL_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Get),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(GET_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
||||||
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
|
};
|
||||||
|
|
||||||
|
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
|
await _pcrbService.UpdateFollowUp(FOLLOW_UP);
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected().Verify(
|
||||||
|
"SendAsync",
|
||||||
|
Times.Once(),
|
||||||
|
ItExpr.Is<HttpRequestMessage>(
|
||||||
|
req =>
|
||||||
|
req.Method == HttpMethod.Put &&
|
||||||
|
req.RequestUri != null &&
|
||||||
|
req.RequestUri.AbsoluteUri.Equals("https://localhost:5000/pcrb/followUp")),
|
||||||
|
ItExpr.IsAny<CancellationToken>());
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected().Verify(
|
||||||
|
"SendAsync",
|
||||||
|
Times.Once(),
|
||||||
|
ItExpr.Is<HttpRequestMessage>(
|
||||||
|
req =>
|
||||||
|
req.Method == HttpMethod.Get &&
|
||||||
|
req.RequestUri != null &&
|
||||||
|
req.RequestUri.AbsoluteUri.Equals("https://localhost:5000/pcrb/followUps?planNumber=123&bypassCache=True")),
|
||||||
|
ItExpr.IsAny<CancellationToken>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateFollowUp_WithNullParam_ShouldThrowException() {
|
||||||
|
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.UpdateFollowUp(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateFollowUp_WithBadResponse_ShouldThrowException() {
|
||||||
|
Mock<HttpMessageHandler> mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Put),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(UNSUCCESSFUL_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
||||||
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
|
};
|
||||||
|
|
||||||
|
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.UpdateFollowUp(FOLLOW_UP));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteFollowUp_WithValidParams_ShouldCallHttpDelete() {
|
||||||
|
Mock<HttpMessageHandler> mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Delete),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(SUCCESSFUL_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
||||||
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
|
};
|
||||||
|
|
||||||
|
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
|
await _pcrbService.DeleteFollowUp(1);
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected().Verify(
|
||||||
|
"SendAsync",
|
||||||
|
Times.Once(),
|
||||||
|
ItExpr.Is<HttpRequestMessage>(
|
||||||
|
req =>
|
||||||
|
req.Method == HttpMethod.Delete &&
|
||||||
|
req.RequestUri != null &&
|
||||||
|
req.RequestUri.AbsoluteUri.Equals("https://localhost:5000/pcrb/followUp?id=1")),
|
||||||
|
ItExpr.IsAny<CancellationToken>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteFollowUp_WithBadId_ShouldThrowException() {
|
||||||
|
await Assert.ThrowsAsync<ArgumentException>(() => _pcrbService.DeleteFollowUp(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DeleteFollowUp_WithBadResponse_ShouldThrowException() {
|
||||||
|
Mock<HttpMessageHandler> mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
||||||
|
|
||||||
|
mockHttpMessageHandler.Protected()
|
||||||
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
|
"SendAsync",
|
||||||
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Delete),
|
||||||
|
ItExpr.IsAny<CancellationToken>())
|
||||||
|
.ReturnsAsync(UNSUCCESSFUL_RESPONSE)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
||||||
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
|
};
|
||||||
|
|
||||||
|
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<Exception>(() => _pcrbService.DeleteFollowUp(1));
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text.Json;
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using MesaFabApproval.Client.Services;
|
using MesaFabApproval.Client.Services;
|
||||||
using MesaFabApproval.Shared.Models;
|
using MesaFabApproval.Shared.Models;
|
||||||
@ -11,6 +12,8 @@ using Moq.Protected;
|
|||||||
|
|
||||||
using MudBlazor;
|
using MudBlazor;
|
||||||
|
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
namespace MesaFabApproval.Client.Test;
|
namespace MesaFabApproval.Client.Test;
|
||||||
|
|
||||||
public class PCRBServiceTests {
|
public class PCRBServiceTests {
|
||||||
@ -18,330 +21,136 @@ public class PCRBServiceTests {
|
|||||||
private readonly Mock<IHttpClientFactory> _mockHttpClientFactory;
|
private readonly Mock<IHttpClientFactory> _mockHttpClientFactory;
|
||||||
private readonly Mock<ISnackbar> _mockSnackbar;
|
private readonly Mock<ISnackbar> _mockSnackbar;
|
||||||
private readonly Mock<IUserService> _mockUserService;
|
private readonly Mock<IUserService> _mockUserService;
|
||||||
|
private readonly Mock<PCRB> _mockPCRB;
|
||||||
|
private readonly Mock<Approval> _mockApproval;
|
||||||
|
|
||||||
private readonly PCRBService _pcrbService;
|
private readonly PCRBService _pcrbService;
|
||||||
|
|
||||||
private static IEnumerable<PCRBFollowUp> FOLLOW_UPS = new List<PCRBFollowUp>() {
|
|
||||||
new PCRBFollowUp { ID = 1, PlanNumber = 1, Step = 1, FollowUpDate = DateTime.Now }
|
|
||||||
};
|
|
||||||
|
|
||||||
private static HttpResponseMessage SUCCESSFUL_RESPONSE = new HttpResponseMessage(HttpStatusCode.OK);
|
|
||||||
private static HttpResponseMessage UNSUCCESSFUL_RESPONSE = new HttpResponseMessage(HttpStatusCode.InternalServerError);
|
|
||||||
|
|
||||||
public static class MockMemoryCacheService {
|
|
||||||
public static Mock<IMemoryCache> GetMemoryCache(object expectedValue) {
|
|
||||||
Mock<IMemoryCache> mockMemoryCache = new Mock<IMemoryCache>();
|
|
||||||
mockMemoryCache
|
|
||||||
.Setup(x => x.TryGetValue(It.IsAny<object>(), out expectedValue))
|
|
||||||
.Returns(true);
|
|
||||||
mockMemoryCache
|
|
||||||
.Setup(x => x.CreateEntry(It.IsAny<object>()))
|
|
||||||
.Returns(Mock.Of<ICacheEntry>());
|
|
||||||
return mockMemoryCache;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public PCRBServiceTests() {
|
public PCRBServiceTests() {
|
||||||
_mockCache = MockMemoryCacheService.GetMemoryCache(FOLLOW_UPS);
|
_mockCache = new Mock<IMemoryCache>();
|
||||||
_mockHttpClientFactory = new Mock<IHttpClientFactory>();
|
_mockHttpClientFactory = new Mock<IHttpClientFactory>();
|
||||||
_mockSnackbar = new Mock<ISnackbar>();
|
_mockSnackbar = new Mock<ISnackbar>();
|
||||||
_mockUserService = new Mock<IUserService>();
|
_mockUserService = new Mock<IUserService>();
|
||||||
|
_mockPCRB = new Mock<PCRB>();
|
||||||
|
_mockApproval = new Mock<Approval>();
|
||||||
|
|
||||||
_pcrbService = new PCRBService(
|
_pcrbService = new PCRBService(
|
||||||
_mockCache.Object,
|
_mockCache.Object,
|
||||||
_mockHttpClientFactory.Object,
|
_mockHttpClientFactory.Object,
|
||||||
_mockSnackbar.Object,
|
_mockSnackbar.Object,
|
||||||
_mockUserService.Object);
|
_mockUserService.Object
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task CreateFollowUp_WithValidParams_ShouldCallHttpPost_AndRefreshCache() {
|
public async Task NotifyApprover_ShouldSendNotification() {
|
||||||
PCRBFollowUp followUp = new PCRBFollowUp {
|
PCRBNotification notification = new PCRBNotification {
|
||||||
ID = 1,
|
Message = "Test Message",
|
||||||
PlanNumber = 123,
|
PCRB = _mockPCRB.Object,
|
||||||
Step = 1,
|
Approval = _mockApproval.Object
|
||||||
FollowUpDate = DateTime.Now,
|
|
||||||
Comments = "Test"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
HttpResponseMessage getResponse = new HttpResponseMessage {
|
Mock<HttpMessageHandler> handlerMock = new Mock<HttpMessageHandler>();
|
||||||
StatusCode = HttpStatusCode.OK,
|
handlerMock
|
||||||
Content = new StringContent(JsonSerializer.Serialize(new List<PCRBFollowUp> { followUp }))
|
.Protected()
|
||||||
};
|
|
||||||
|
|
||||||
var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
|
||||||
mockHttpMessageHandler.Protected()
|
|
||||||
.Setup<Task<HttpResponseMessage>>(
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
"SendAsync",
|
"SendAsync",
|
||||||
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Post),
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Post),
|
||||||
ItExpr.IsAny<CancellationToken>())
|
ItExpr.IsAny<CancellationToken>()
|
||||||
.ReturnsAsync(SUCCESSFUL_RESPONSE)
|
)
|
||||||
|
.ReturnsAsync(new HttpResponseMessage {
|
||||||
|
StatusCode = HttpStatusCode.OK
|
||||||
|
})
|
||||||
.Verifiable();
|
.Verifiable();
|
||||||
|
|
||||||
mockHttpMessageHandler.Protected()
|
HttpClient httpClient = new HttpClient(handlerMock.Object) {
|
||||||
.Setup<Task<HttpResponseMessage>>(
|
|
||||||
"SendAsync",
|
|
||||||
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Get),
|
|
||||||
ItExpr.IsAny<CancellationToken>())
|
|
||||||
.ReturnsAsync(getResponse)
|
|
||||||
.Verifiable();
|
|
||||||
|
|
||||||
var httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
|
||||||
BaseAddress = new Uri("https://localhost:5000")
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
};
|
};
|
||||||
|
|
||||||
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
await _pcrbService.CreateFollowUp(followUp);
|
await _pcrbService.NotifyApprover(notification);
|
||||||
|
|
||||||
mockHttpMessageHandler.Protected().Verify(
|
handlerMock.Protected().Verify(
|
||||||
"SendAsync",
|
"SendAsync",
|
||||||
Times.Once(),
|
Times.Once(),
|
||||||
ItExpr.Is<HttpRequestMessage>(
|
ItExpr.Is<HttpRequestMessage>(req =>
|
||||||
req =>
|
req.Method == HttpMethod.Post &&
|
||||||
req.Method == HttpMethod.Post &&
|
req.RequestUri == new Uri("https://localhost:5000/pcrb/notify/approver")
|
||||||
req.RequestUri != null &&
|
),
|
||||||
req.RequestUri.AbsoluteUri.Equals("https://localhost:5000/pcrb/followUp")),
|
ItExpr.IsAny<CancellationToken>()
|
||||||
ItExpr.IsAny<CancellationToken>());
|
);
|
||||||
|
|
||||||
mockHttpMessageHandler.Protected().Verify(
|
|
||||||
"SendAsync",
|
|
||||||
Times.Once(),
|
|
||||||
ItExpr.Is<HttpRequestMessage>(
|
|
||||||
req =>
|
|
||||||
req.Method == HttpMethod.Get &&
|
|
||||||
req.RequestUri != null &&
|
|
||||||
req.RequestUri.AbsoluteUri.Equals("https://localhost:5000/pcrb/followUps?planNumber=123&bypassCache=True")),
|
|
||||||
ItExpr.IsAny<CancellationToken>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task CreateFollowUp_WithBadResponse_ShouldThrowException() {
|
public async Task NotifyApprover_ShouldThrowException_WhenResponseIsNotSuccess() {
|
||||||
PCRBFollowUp followUp = new PCRBFollowUp {
|
PCRBNotification notification = new PCRBNotification {
|
||||||
ID = 1,
|
Message = "Test Message",
|
||||||
PlanNumber = 123,
|
PCRB = _mockPCRB.Object,
|
||||||
Step = 1,
|
Approval = _mockApproval.Object
|
||||||
FollowUpDate = DateTime.Now,
|
|
||||||
Comments = "Test"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
var handlerMock = new Mock<HttpMessageHandler>();
|
||||||
mockHttpMessageHandler.Protected()
|
handlerMock
|
||||||
|
.Protected()
|
||||||
.Setup<Task<HttpResponseMessage>>(
|
.Setup<Task<HttpResponseMessage>>(
|
||||||
"SendAsync",
|
"SendAsync",
|
||||||
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Post),
|
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Post),
|
||||||
ItExpr.IsAny<CancellationToken>())
|
ItExpr.IsAny<CancellationToken>()
|
||||||
.ReturnsAsync(UNSUCCESSFUL_RESPONSE)
|
)
|
||||||
.Verifiable();
|
.ReturnsAsync(new HttpResponseMessage {
|
||||||
|
StatusCode = HttpStatusCode.BadRequest,
|
||||||
|
ReasonPhrase = "Bad Request"
|
||||||
|
});
|
||||||
|
|
||||||
var httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
HttpClient httpClient = new HttpClient(handlerMock.Object) {
|
||||||
BaseAddress = new Uri("https://localhost:5000")
|
|
||||||
};
|
|
||||||
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<Exception>(() => _pcrbService.CreateFollowUp(followUp));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task CreateFollowUp_WithNullParam_ShouldThrowException() {
|
|
||||||
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.CreateFollowUp(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetFollowUpsByPlanNumber_WithBypassCache_ShouldCallHttpGetAndReturnFollowUps() {
|
|
||||||
PCRBFollowUp followUp = new PCRBFollowUp {
|
|
||||||
ID = 1,
|
|
||||||
PlanNumber = 123,
|
|
||||||
Step = 1,
|
|
||||||
FollowUpDate = DateTime.Now,
|
|
||||||
Comments = "Test"
|
|
||||||
};
|
|
||||||
|
|
||||||
HttpResponseMessage getResponse = new HttpResponseMessage {
|
|
||||||
StatusCode = HttpStatusCode.OK,
|
|
||||||
Content = new StringContent(JsonSerializer.Serialize(new List<PCRBFollowUp> { followUp }))
|
|
||||||
};
|
|
||||||
|
|
||||||
var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
|
||||||
|
|
||||||
mockHttpMessageHandler.Protected()
|
|
||||||
.Setup<Task<HttpResponseMessage>>(
|
|
||||||
"SendAsync",
|
|
||||||
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Get),
|
|
||||||
ItExpr.IsAny<CancellationToken>())
|
|
||||||
.ReturnsAsync(getResponse)
|
|
||||||
.Verifiable();
|
|
||||||
|
|
||||||
var httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
|
||||||
BaseAddress = new Uri("https://localhost:5000")
|
|
||||||
};
|
|
||||||
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
|
||||||
|
|
||||||
IEnumerable<PCRBFollowUp> followUps = await _pcrbService.GetFollowUpsByPlanNumber(123, true);
|
|
||||||
|
|
||||||
mockHttpMessageHandler.Protected().Verify(
|
|
||||||
"SendAsync",
|
|
||||||
Times.Once(),
|
|
||||||
ItExpr.Is<HttpRequestMessage>(
|
|
||||||
req =>
|
|
||||||
req.Method == HttpMethod.Get &&
|
|
||||||
req.RequestUri != null &&
|
|
||||||
req.RequestUri.AbsoluteUri.Equals("https://localhost:5000/pcrb/followUps?planNumber=123&bypassCache=True")),
|
|
||||||
ItExpr.IsAny<CancellationToken>());
|
|
||||||
|
|
||||||
Assert.Single(followUps);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetFollowUpsByPlanNumber_WithoutBypassCache_ShouldReturnFollowUpsFromCache() {
|
|
||||||
IEnumerable<PCRBFollowUp> followUps = await _pcrbService.GetFollowUpsByPlanNumber(1, false);
|
|
||||||
Assert.Single(followUps);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetFollowUpsByPlanNumber_WithBadResponse_ShouldThrowException() {
|
|
||||||
var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
|
||||||
|
|
||||||
mockHttpMessageHandler.Protected()
|
|
||||||
.Setup<Task<HttpResponseMessage>>(
|
|
||||||
"SendAsync",
|
|
||||||
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Get),
|
|
||||||
ItExpr.IsAny<CancellationToken>())
|
|
||||||
.ReturnsAsync(UNSUCCESSFUL_RESPONSE)
|
|
||||||
.Verifiable();
|
|
||||||
|
|
||||||
var httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
|
||||||
BaseAddress = new Uri("https://localhost:5000")
|
BaseAddress = new Uri("https://localhost:5000")
|
||||||
};
|
};
|
||||||
|
|
||||||
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||||
|
|
||||||
await Assert.ThrowsAsync<Exception>(() => _pcrbService.GetFollowUpsByPlanNumber(1, true));
|
Exception exception = await Assert.ThrowsAsync<Exception>(() => _pcrbService.NotifyApprover(notification));
|
||||||
|
Assert.Equal("Unable to notify PCRB approver, because Bad Request", exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task UpdateFollowUp_WithValidParams_ShouldCallHttpPut() {
|
public async Task NotifyApprover_ShouldThrowException_WhenNotificationIsNull() {
|
||||||
PCRBFollowUp followUp = new PCRBFollowUp {
|
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.NotifyApprover(null));
|
||||||
ID = 1,
|
|
||||||
PlanNumber = 123,
|
|
||||||
Step = 1,
|
|
||||||
FollowUpDate = DateTime.Now,
|
|
||||||
Comments = "Test"
|
|
||||||
};
|
|
||||||
|
|
||||||
var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
|
||||||
|
|
||||||
mockHttpMessageHandler.Protected()
|
|
||||||
.Setup<Task<HttpResponseMessage>>(
|
|
||||||
"SendAsync",
|
|
||||||
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Put),
|
|
||||||
ItExpr.IsAny<CancellationToken>())
|
|
||||||
.ReturnsAsync(SUCCESSFUL_RESPONSE)
|
|
||||||
.Verifiable();
|
|
||||||
|
|
||||||
var httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
|
||||||
BaseAddress = new Uri("https://localhost:5000")
|
|
||||||
};
|
|
||||||
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
|
||||||
|
|
||||||
await _pcrbService.UpdateFollowUp(followUp);
|
|
||||||
|
|
||||||
mockHttpMessageHandler.Protected().Verify(
|
|
||||||
"SendAsync",
|
|
||||||
Times.Once(),
|
|
||||||
ItExpr.Is<HttpRequestMessage>(
|
|
||||||
req =>
|
|
||||||
req.Method == HttpMethod.Put &&
|
|
||||||
req.RequestUri != null &&
|
|
||||||
req.RequestUri.AbsoluteUri.Equals("https://localhost:5000/pcrb/followUp")),
|
|
||||||
ItExpr.IsAny<CancellationToken>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task UpdateFollowUp_WithNullParam_ShouldThrowException() {
|
public async Task NotifyApprover_ShouldThrowException_WhenPCRBIsNull() {
|
||||||
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.UpdateFollowUp(null));
|
PCRBNotification notification = new PCRBNotification {
|
||||||
|
Message = "Test Message",
|
||||||
|
PCRB = null,
|
||||||
|
Approval = _mockApproval.Object
|
||||||
|
};
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.NotifyApprover(notification));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task UpdateFollowUp_WithBadResponse_ShouldThrowException() {
|
public async Task NotifyApprover_ShouldThrowException_WhenApprovalIsNull() {
|
||||||
PCRBFollowUp followUp = new PCRBFollowUp {
|
PCRBNotification notification = new PCRBNotification {
|
||||||
ID = 1,
|
Message = "Test Message",
|
||||||
PlanNumber = 123,
|
PCRB = _mockPCRB.Object,
|
||||||
Step = 1,
|
Approval = null
|
||||||
FollowUpDate = DateTime.Now,
|
|
||||||
Comments = "Test"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
await Assert.ThrowsAsync<ArgumentNullException>(() => _pcrbService.NotifyApprover(notification));
|
||||||
|
|
||||||
mockHttpMessageHandler.Protected()
|
|
||||||
.Setup<Task<HttpResponseMessage>>(
|
|
||||||
"SendAsync",
|
|
||||||
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Put),
|
|
||||||
ItExpr.IsAny<CancellationToken>())
|
|
||||||
.ReturnsAsync(UNSUCCESSFUL_RESPONSE)
|
|
||||||
.Verifiable();
|
|
||||||
|
|
||||||
var httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
|
||||||
BaseAddress = new Uri("https://localhost:5000")
|
|
||||||
};
|
|
||||||
|
|
||||||
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
|
||||||
|
|
||||||
await Assert.ThrowsAsync<Exception>(() => _pcrbService.UpdateFollowUp(followUp));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task DeleteFollowUp_WithValidParams_ShouldCallHttpDelete() {
|
public async Task NotifyApprover_ShouldThrowException_WhenMessageIsNullOrEmpty() {
|
||||||
var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
PCRBNotification notification = new PCRBNotification {
|
||||||
|
Message = null,
|
||||||
mockHttpMessageHandler.Protected()
|
PCRB = _mockPCRB.Object,
|
||||||
.Setup<Task<HttpResponseMessage>>(
|
Approval = _mockApproval.Object
|
||||||
"SendAsync",
|
|
||||||
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Delete),
|
|
||||||
ItExpr.IsAny<CancellationToken>())
|
|
||||||
.ReturnsAsync(SUCCESSFUL_RESPONSE)
|
|
||||||
.Verifiable();
|
|
||||||
|
|
||||||
var httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
|
||||||
BaseAddress = new Uri("https://localhost:5000")
|
|
||||||
};
|
|
||||||
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
|
||||||
|
|
||||||
await _pcrbService.DeleteFollowUp(1);
|
|
||||||
|
|
||||||
mockHttpMessageHandler.Protected().Verify(
|
|
||||||
"SendAsync",
|
|
||||||
Times.Once(),
|
|
||||||
ItExpr.Is<HttpRequestMessage>(
|
|
||||||
req =>
|
|
||||||
req.Method == HttpMethod.Delete &&
|
|
||||||
req.RequestUri != null &&
|
|
||||||
req.RequestUri.AbsoluteUri.Equals("https://localhost:5000/pcrb/followUp?id=1")),
|
|
||||||
ItExpr.IsAny<CancellationToken>());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task DeleteFollowUp_WithBadId_ShouldThrowException() {
|
|
||||||
await Assert.ThrowsAsync<ArgumentException>(() => _pcrbService.DeleteFollowUp(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task DeleteFollowUp_WithBadResponse_ShouldThrowException() {
|
|
||||||
var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
|
||||||
|
|
||||||
mockHttpMessageHandler.Protected()
|
|
||||||
.Setup<Task<HttpResponseMessage>>(
|
|
||||||
"SendAsync",
|
|
||||||
ItExpr.Is<HttpRequestMessage>(_ => _.Method == HttpMethod.Delete),
|
|
||||||
ItExpr.IsAny<CancellationToken>())
|
|
||||||
.ReturnsAsync(UNSUCCESSFUL_RESPONSE)
|
|
||||||
.Verifiable();
|
|
||||||
|
|
||||||
var httpClient = new HttpClient(mockHttpMessageHandler.Object) {
|
|
||||||
BaseAddress = new Uri("https://localhost:5000")
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
await Assert.ThrowsAsync<ArgumentException>(() => _pcrbService.NotifyApprover(notification));
|
||||||
|
|
||||||
await Assert.ThrowsAsync<Exception>(() => _pcrbService.DeleteFollowUp(1));
|
notification.Message = string.Empty;
|
||||||
|
await Assert.ThrowsAsync<ArgumentException>(() => _pcrbService.NotifyApprover(notification));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,15 +15,15 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="8.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="8.0.14" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.14" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.8" PrivateAssets="all" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.14" PrivateAssets="all" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.3.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
|
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.3.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="8.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="8.0.14" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
|
||||||
<PackageReference Include="MudBlazor" Version="7.6.0" />
|
<PackageReference Include="MudBlazor" Version="8.3.0" />
|
||||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.0.1" />
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.6.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
using MesaFabApproval.Client.Services;
|
using MesaFabApproval.Client.Services;
|
||||||
|
using MesaFabApproval.Shared.Models;
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.AspNetCore.WebUtilities;
|
using Microsoft.AspNetCore.WebUtilities;
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
|
||||||
using MudBlazor;
|
using MudBlazor;
|
||||||
|
|
||||||
@ -13,8 +15,8 @@ public partial class AuthenticatedRedirect {
|
|||||||
[Inject] MesaFabApprovalAuthStateProvider authStateProvider { get; set; }
|
[Inject] MesaFabApprovalAuthStateProvider authStateProvider { get; set; }
|
||||||
[Inject] IAuthenticationService authService { get; set; }
|
[Inject] IAuthenticationService authService { get; set; }
|
||||||
[Inject] IUserService userService { get; set; }
|
[Inject] IUserService userService { get; set; }
|
||||||
[Inject] ISnackbar snackbar { get; set; }
|
|
||||||
[Inject] NavigationManager navigationManager { get; set; }
|
[Inject] NavigationManager navigationManager { get; set; }
|
||||||
|
[Inject] IMemoryCache cache { get; set; }
|
||||||
|
|
||||||
private string? _jwt;
|
private string? _jwt;
|
||||||
private string? _refreshToken;
|
private string? _refreshToken;
|
||||||
@ -53,13 +55,16 @@ public partial class AuthenticatedRedirect {
|
|||||||
await authStateProvider.StateHasChanged(principal);
|
await authStateProvider.StateHasChanged(principal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AuthTokens authTokens = await authService.GetAuthTokens();
|
||||||
|
|
||||||
if (authStateProvider.CurrentUser is not null && !string.IsNullOrWhiteSpace(_redirectPath)) {
|
if (authStateProvider.CurrentUser is not null && !string.IsNullOrWhiteSpace(_redirectPath)) {
|
||||||
navigationManager.NavigateTo(_redirectPath);
|
navigationManager.NavigateTo(_redirectPath);
|
||||||
} else {
|
} else {
|
||||||
await authStateProvider.Logout();
|
await authStateProvider.Logout();
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(_redirectPath)) {
|
if (!string.IsNullOrWhiteSpace(_redirectPath)) {
|
||||||
navigationManager.NavigateTo($"login/{_redirectPath}");
|
cache.Set("redirectUrl", _redirectPath);
|
||||||
|
navigationManager.NavigateTo($"login?redirectPath={_redirectPath}");
|
||||||
} else {
|
} else {
|
||||||
navigationManager.NavigateTo("login");
|
navigationManager.NavigateTo("login");
|
||||||
}
|
}
|
||||||
@ -68,7 +73,8 @@ public partial class AuthenticatedRedirect {
|
|||||||
await authStateProvider.Logout();
|
await authStateProvider.Logout();
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(_redirectPath)) {
|
if (!string.IsNullOrWhiteSpace(_redirectPath)) {
|
||||||
navigationManager.NavigateTo($"login/{_redirectPath}");
|
cache.Set("redirectUrl", _redirectPath);
|
||||||
|
navigationManager.NavigateTo($"login?redirectPath={_redirectPath}");
|
||||||
} else {
|
} else {
|
||||||
navigationManager.NavigateTo("login");
|
navigationManager.NavigateTo("login");
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
</MudDialog>
|
</MudDialog>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[CascadingParameter] MudDialogInstance MudDialog { get; set; }
|
[CascadingParameter] IMudDialogInstance MudDialog { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string comments { get; set; } = "";
|
public string comments { get; set; } = "";
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
</MudDialog>
|
</MudDialog>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[CascadingParameter] MudDialogInstance MudDialog { get; set; }
|
[CascadingParameter] IMudDialogInstance MudDialog { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string comments { get; set; } = "";
|
public string comments { get; set; } = "";
|
||||||
|
@ -143,7 +143,7 @@
|
|||||||
</MudDialog>
|
</MudDialog>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[CascadingParameter] MudDialogInstance MudDialog { get; set; }
|
[CascadingParameter] IMudDialogInstance MudDialog { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public MRBAction mrbAction { get; set; }
|
public MRBAction mrbAction { get; set; }
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
</MudOverlay>
|
</MudOverlay>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[CascadingParameter] MudDialogInstance MudDialog { get; set; }
|
[CascadingParameter] IMudDialogInstance MudDialog { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public User selectedUser { get; set; }
|
public User selectedUser { get; set; }
|
||||||
|
@ -74,7 +74,7 @@
|
|||||||
|
|
||||||
@code {
|
@code {
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
MudDialogInstance MudDialog { get; set; }
|
IMudDialogInstance MudDialog { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public required PCR3Document document { get; set; }
|
public required PCR3Document document { get; set; }
|
||||||
|
@ -73,7 +73,7 @@
|
|||||||
|
|
||||||
@code {
|
@code {
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
MudDialogInstance MudDialog { get; set; }
|
IMudDialogInstance MudDialog { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public int planNumber { get; set; } = 0;
|
public int planNumber { get; set; } = 0;
|
||||||
|
@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
@code {
|
@code {
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
MudDialogInstance MudDialog { get; set; }
|
IMudDialogInstance MudDialog { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public int planNumber { get; set; } = 0;
|
public int planNumber { get; set; } = 0;
|
||||||
|
@ -58,7 +58,7 @@
|
|||||||
</MudDialog>
|
</MudDialog>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[CascadingParameter] MudDialogInstance MudDialog { get; set; }
|
[CascadingParameter] IMudDialogInstance MudDialog { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public int planNumber { get; set; } = 0;
|
public int planNumber { get; set; } = 0;
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
</MudOverlay>
|
</MudOverlay>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[CascadingParameter] MudDialogInstance MudDialog { get; set; }
|
[CascadingParameter] IMudDialogInstance MudDialog { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public User selectedUser { get; set; }
|
public User selectedUser { get; set; }
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
</MudTableSortLabel>
|
</MudTableSortLabel>
|
||||||
</MudTh>
|
</MudTh>
|
||||||
<MudTh>
|
<MudTh>
|
||||||
<MudTableSortLabel SortBy="new Func<Approval,object>(x=>x.SubRoleCategoryItem)">
|
<MudTableSortLabel SortBy="new Func<Approval,object>(x=>GetRoleName(x))">
|
||||||
Role
|
Role
|
||||||
</MudTableSortLabel>
|
</MudTableSortLabel>
|
||||||
</MudTh>
|
</MudTh>
|
||||||
@ -47,7 +47,7 @@
|
|||||||
<MudLink OnClick="@(() => FollowLink(context.IssueID))">@context.IssueID</MudLink>
|
<MudLink OnClick="@(() => FollowLink(context.IssueID))">@context.IssueID</MudLink>
|
||||||
}
|
}
|
||||||
</MudTd>
|
</MudTd>
|
||||||
<MudTd DataLabel="Role">@context.SubRoleCategoryItem</MudTd>
|
<MudTd DataLabel="Role">@(GetRoleName(context))</MudTd>
|
||||||
<MudTd DataLabel="Assigned Date">@DateTimeUtilities.GetDateAsStringMinDefault(context.AssignedDate)</MudTd>
|
<MudTd DataLabel="Assigned Date">@DateTimeUtilities.GetDateAsStringMinDefault(context.AssignedDate)</MudTd>
|
||||||
<MudTd DataLabel="Step">@context.Step</MudTd>
|
<MudTd DataLabel="Step">@context.Step</MudTd>
|
||||||
</RowTemplate>
|
</RowTemplate>
|
||||||
|
@ -118,7 +118,7 @@ public partial class Dashboard {
|
|||||||
|
|
||||||
private void GoTo(string page) {
|
private void GoTo(string page) {
|
||||||
cache.Set("redirectUrl", page);
|
cache.Set("redirectUrl", page);
|
||||||
navigationManager.NavigateTo("/" + page);
|
navigationManager.NavigateTo(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task GoToExternal(string url, string content) {
|
private async Task GoToExternal(string url, string content) {
|
||||||
@ -154,4 +154,12 @@ public partial class Dashboard {
|
|||||||
if (step < 0 || step > (PCRB.Stages.Length - 1)) return string.Empty;
|
if (step < 0 || step > (PCRB.Stages.Length - 1)) return string.Empty;
|
||||||
else return PCRB.Stages[step];
|
else return PCRB.Stages[step];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetRoleName(Approval approval) {
|
||||||
|
string roleName = approval.SubRoleCategoryItem;
|
||||||
|
if (string.IsNullOrWhiteSpace(roleName)) {
|
||||||
|
roleName = approval.RoleName;
|
||||||
|
}
|
||||||
|
return roleName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
@page "/login"
|
@page "/login"
|
||||||
@page "/login/{redirectUrl}"
|
|
||||||
@page "/login/{redirectUrl}/{redirectUrlSub}"
|
|
||||||
@attribute [AllowAnonymous]
|
@attribute [AllowAnonymous]
|
||||||
@inject MesaFabApprovalAuthStateProvider authStateProvider
|
@inject MesaFabApprovalAuthStateProvider authStateProvider
|
||||||
@inject NavigationManager navManager
|
@inject NavigationManager navManager
|
||||||
@ -46,68 +44,5 @@
|
|||||||
}
|
}
|
||||||
</MudButton>
|
</MudButton>
|
||||||
<MudDivider />
|
<MudDivider />
|
||||||
@* <MudButton
|
|
||||||
Variant="Variant.Filled"
|
|
||||||
Color="Color.Tertiary"
|
|
||||||
Class="m-1"
|
|
||||||
OnClick="LoginLocal" >
|
|
||||||
@if (processingLocal) {
|
|
||||||
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
|
||||||
<MudText>Processing</MudText>
|
|
||||||
} else {
|
|
||||||
<MudText>Log In (SSO)</MudText>
|
|
||||||
}
|
|
||||||
</MudButton> *@
|
|
||||||
</MudForm>
|
</MudForm>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
|
|
||||||
@code {
|
|
||||||
[Parameter]
|
|
||||||
public string? redirectUrl { get; set; }
|
|
||||||
[Parameter]
|
|
||||||
public string? redirectUrlSub { get; set; }
|
|
||||||
private bool success;
|
|
||||||
private bool processing = false;
|
|
||||||
private bool processingLocal = false;
|
|
||||||
private string[] errors = { };
|
|
||||||
private string? username;
|
|
||||||
private string? password;
|
|
||||||
|
|
||||||
private async Task SubmitLogin() {
|
|
||||||
processing = true;
|
|
||||||
if (string.IsNullOrWhiteSpace(username)) snackbar.Add("Username is required!", Severity.Error);
|
|
||||||
else if (string.IsNullOrWhiteSpace(password)) snackbar.Add("Password is required!", Severity.Error);
|
|
||||||
else {
|
|
||||||
await authStateProvider.LoginAsync(username, password);
|
|
||||||
if (!string.IsNullOrWhiteSpace(redirectUrl) && !string.IsNullOrWhiteSpace(redirectUrlSub)) {
|
|
||||||
navManager.NavigateTo($"{redirectUrl}/{redirectUrlSub}");
|
|
||||||
} else if (!string.IsNullOrWhiteSpace(redirectUrl)) {
|
|
||||||
navManager.NavigateTo(redirectUrl);
|
|
||||||
} else {
|
|
||||||
navManager.NavigateTo("dashboard");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
processing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SubmitIfEnter(KeyboardEventArgs e) {
|
|
||||||
if (e.Key == "Enter" && success) {
|
|
||||||
SubmitLogin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LoginLocal() {
|
|
||||||
processingLocal = true;
|
|
||||||
|
|
||||||
await authStateProvider.LoginLocal();
|
|
||||||
if (!string.IsNullOrWhiteSpace(redirectUrl) && !string.IsNullOrWhiteSpace(redirectUrlSub)) {
|
|
||||||
navManager.NavigateTo($"{redirectUrl}/{redirectUrlSub}");
|
|
||||||
} else if (!string.IsNullOrWhiteSpace(redirectUrl)) {
|
|
||||||
navManager.NavigateTo(redirectUrl);
|
|
||||||
} else {
|
|
||||||
navManager.NavigateTo("dashboard");
|
|
||||||
}
|
|
||||||
|
|
||||||
processingLocal = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
53
MesaFabApproval.Client/Pages/Login.razor.cs
Normal file
53
MesaFabApproval.Client/Pages/Login.razor.cs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using Microsoft.AspNetCore.Components.Web;
|
||||||
|
using Microsoft.AspNetCore.WebUtilities;
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
|
||||||
|
using MudBlazor;
|
||||||
|
|
||||||
|
namespace MesaFabApproval.Client.Pages;
|
||||||
|
|
||||||
|
public partial class Login {
|
||||||
|
[Inject] NavigationManager navigationManager { get; set; }
|
||||||
|
[Inject] IMemoryCache cache { get; set; }
|
||||||
|
|
||||||
|
public string? _redirectPath { get; set; }
|
||||||
|
private bool success;
|
||||||
|
private bool processing = false;
|
||||||
|
private string[] errors = { };
|
||||||
|
private string? username;
|
||||||
|
private string? password;
|
||||||
|
|
||||||
|
protected override async Task OnParametersSetAsync() {
|
||||||
|
Uri uri = navigationManager.ToAbsoluteUri(navigationManager.Uri);
|
||||||
|
|
||||||
|
if (QueryHelpers.ParseQuery(uri.Query).TryGetValue("redirectPath", out var redirectPath)) {
|
||||||
|
_redirectPath = System.Net.WebUtility.UrlDecode(redirectPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(_redirectPath)) {
|
||||||
|
_redirectPath = cache.Get<string>("redirectUrl");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SubmitLogin() {
|
||||||
|
processing = true;
|
||||||
|
if (string.IsNullOrWhiteSpace(username)) snackbar.Add("Username is required!", Severity.Error);
|
||||||
|
else if (string.IsNullOrWhiteSpace(password)) snackbar.Add("Password is required!", Severity.Error);
|
||||||
|
else {
|
||||||
|
await authStateProvider.LoginAsync(username, password);
|
||||||
|
if (!string.IsNullOrWhiteSpace(_redirectPath)) {
|
||||||
|
navManager.NavigateTo(_redirectPath);
|
||||||
|
} else {
|
||||||
|
navManager.NavigateTo("dashboard");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
processing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SubmitIfEnter(KeyboardEventArgs e) {
|
||||||
|
if (e.Key == "Enter" && success) {
|
||||||
|
SubmitLogin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,4 @@
|
|||||||
@page "/mrb/all"
|
@page "/mrb/all"
|
||||||
@using System.Globalization
|
|
||||||
@inject IMRBService mrbService
|
|
||||||
@inject ISnackbar snackbar
|
|
||||||
@inject IMemoryCache cache
|
|
||||||
@inject NavigationManager navigationManager
|
|
||||||
|
|
||||||
<PageTitle>MRB</PageTitle>
|
<PageTitle>MRB</PageTitle>
|
||||||
|
|
||||||
@ -78,42 +73,3 @@
|
|||||||
<MudOverlay @bind-Visible=inProcess DarkBackground="true" AutoClose="false">
|
<MudOverlay @bind-Visible=inProcess DarkBackground="true" AutoClose="false">
|
||||||
<MudProgressCircular Color="Color.Info" Size="Size.Large" Indeterminate="true" />
|
<MudProgressCircular Color="Color.Info" Size="Size.Large" Indeterminate="true" />
|
||||||
</MudOverlay>
|
</MudOverlay>
|
||||||
|
|
||||||
@code {
|
|
||||||
private bool inProcess = false;
|
|
||||||
private string searchString = "";
|
|
||||||
private IEnumerable<MRB> allMrbs = new List<MRB>();
|
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync() {
|
|
||||||
inProcess = true;
|
|
||||||
try {
|
|
||||||
if (mrbService is null) {
|
|
||||||
throw new Exception("MRB service not injected!");
|
|
||||||
} else {
|
|
||||||
allMrbs = await mrbService.GetAllMRBs(false);
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
snackbar.Add(ex.Message, Severity.Error);
|
|
||||||
}
|
|
||||||
inProcess = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool FilterFuncForTable(MRB mrb) => FilterFunc(mrb, searchString);
|
|
||||||
|
|
||||||
private bool FilterFunc(MRB mrb, string searchString) {
|
|
||||||
if (string.IsNullOrWhiteSpace(searchString))
|
|
||||||
return true;
|
|
||||||
if (mrb.Title.ToLower().Contains(searchString.Trim().ToLower()))
|
|
||||||
return true;
|
|
||||||
if (mrb.OriginatorName.ToLower().Contains(searchString.Trim().ToLower()))
|
|
||||||
return true;
|
|
||||||
if (mrb.MRBNumber.ToString().Contains(searchString.Trim()))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GoTo(string page) {
|
|
||||||
cache.Set("redirectUrl", page);
|
|
||||||
navigationManager.NavigateTo(page);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
55
MesaFabApproval.Client/Pages/MRBAll.razor.cs
Normal file
55
MesaFabApproval.Client/Pages/MRBAll.razor.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
using MesaFabApproval.Client.Services;
|
||||||
|
using MesaFabApproval.Shared.Models;
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
|
||||||
|
using MudBlazor;
|
||||||
|
|
||||||
|
namespace MesaFabApproval.Client.Pages;
|
||||||
|
|
||||||
|
public partial class MRBAll {
|
||||||
|
[Inject] IMRBService mrbService { get; set; }
|
||||||
|
[Inject] ISnackbar snackbar { get; set; }
|
||||||
|
[Inject] IMemoryCache cache { get; set; }
|
||||||
|
[Inject] NavigationManager navigationManager { get; set; }
|
||||||
|
|
||||||
|
private bool inProcess = false;
|
||||||
|
private string searchString = "";
|
||||||
|
private IEnumerable<MRB> allMrbs = new List<MRB>();
|
||||||
|
|
||||||
|
protected override async Task OnParametersSetAsync() {
|
||||||
|
inProcess = true;
|
||||||
|
try {
|
||||||
|
cache.Set("redirectUrl", "mrb/all");
|
||||||
|
|
||||||
|
if (mrbService is null) {
|
||||||
|
throw new Exception("MRB service not injected!");
|
||||||
|
} else {
|
||||||
|
allMrbs = await mrbService.GetAllMRBs(false);
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
snackbar.Add(ex.Message, Severity.Error);
|
||||||
|
}
|
||||||
|
inProcess = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool FilterFuncForTable(MRB mrb) => FilterFunc(mrb, searchString);
|
||||||
|
|
||||||
|
private bool FilterFunc(MRB mrb, string searchString) {
|
||||||
|
if (string.IsNullOrWhiteSpace(searchString))
|
||||||
|
return true;
|
||||||
|
if (mrb.Title.ToLower().Contains(searchString.Trim().ToLower()))
|
||||||
|
return true;
|
||||||
|
if (mrb.OriginatorName.ToLower().Contains(searchString.Trim().ToLower()))
|
||||||
|
return true;
|
||||||
|
if (mrb.MRBNumber.ToString().Contains(searchString.Trim()))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GoTo(string page) {
|
||||||
|
cache.Set("redirectUrl", page);
|
||||||
|
navigationManager.NavigateTo(page);
|
||||||
|
}
|
||||||
|
}
|
@ -65,6 +65,8 @@ public partial class MRBSingle {
|
|||||||
protected override async Task OnParametersSetAsync() {
|
protected override async Task OnParametersSetAsync() {
|
||||||
processing = true;
|
processing = true;
|
||||||
try {
|
try {
|
||||||
|
cache.Set("redirectUrl", $"mrb/{mrbNumber}");
|
||||||
|
|
||||||
allActiveUsers = await userService.GetAllActiveUsers();
|
allActiveUsers = await userService.GetAllActiveUsers();
|
||||||
currentUser = authStateProvider.CurrentUser;
|
currentUser = authStateProvider.CurrentUser;
|
||||||
currentUrl = navigationManager.Uri;
|
currentUrl = navigationManager.Uri;
|
||||||
@ -285,7 +287,7 @@ public partial class MRBSingle {
|
|||||||
string? comments = "";
|
string? comments = "";
|
||||||
|
|
||||||
DialogParameters<Comments> parameters = new DialogParameters<Comments> { { x => x.comments, comments } };
|
DialogParameters<Comments> parameters = new DialogParameters<Comments> { { x => x.comments, comments } };
|
||||||
var dialog = dialogService.Show<Comments>($"Approval Comments", parameters);
|
var dialog = await dialogService.ShowAsync<Comments>($"Approval Comments", parameters);
|
||||||
|
|
||||||
var result = await dialog.Result;
|
var result = await dialog.Result;
|
||||||
|
|
||||||
@ -412,7 +414,7 @@ public partial class MRBSingle {
|
|||||||
if (currentUser is null) {
|
if (currentUser is null) {
|
||||||
recallInProcess = false;
|
recallInProcess = false;
|
||||||
snackbar.Add("You must be logged in to recall this MRB", Severity.Error);
|
snackbar.Add("You must be logged in to recall this MRB", Severity.Error);
|
||||||
navigationManager.NavigateTo($"login/mrb/{mrb.MRBNumber}");
|
navigationManager.NavigateTo($"login?redirectPath=mrb/{mrb.MRBNumber}");
|
||||||
} else {
|
} else {
|
||||||
await mrbService.RecallMRB(mrb, currentUser);
|
await mrbService.RecallMRB(mrb, currentUser);
|
||||||
mrbApprovals = await approvalService.GetApprovalsForIssueId(mrb.MRBNumber, true);
|
mrbApprovals = await approvalService.GetApprovalsForIssueId(mrb.MRBNumber, true);
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
@page "/pcrb/all"
|
@page "/pcrb/all"
|
||||||
@using System.Globalization
|
|
||||||
@inject IPCRBService pcrbService
|
|
||||||
@inject ISnackbar snackbar
|
|
||||||
@inject IMemoryCache cache
|
|
||||||
@inject NavigationManager navigationManager
|
|
||||||
|
|
||||||
<PageTitle>PCRB</PageTitle>
|
<PageTitle>PCRB</PageTitle>
|
||||||
|
|
||||||
@ -25,6 +20,7 @@
|
|||||||
Adornment="Adornment.Start"
|
Adornment="Adornment.Start"
|
||||||
AdornmentIcon="@Icons.Material.Filled.Search"
|
AdornmentIcon="@Icons.Material.Filled.Search"
|
||||||
IconSize="Size.Medium"
|
IconSize="Size.Medium"
|
||||||
|
Immediate
|
||||||
Class="mt-0" />
|
Class="mt-0" />
|
||||||
</ToolBarContent>
|
</ToolBarContent>
|
||||||
<HeaderContent>
|
<HeaderContent>
|
||||||
@ -43,19 +39,37 @@
|
|||||||
Owner
|
Owner
|
||||||
</MudTableSortLabel>
|
</MudTableSortLabel>
|
||||||
</MudTh>
|
</MudTh>
|
||||||
<MudTh>Stage</MudTh>
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortBy="new Func<PCRB,object>(x=>x.Type)">
|
||||||
|
Type
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortBy="new Func<PCRB, object>(x=>GetStageName(x.CurrentStep))">
|
||||||
|
Stage
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
<MudTh>
|
<MudTh>
|
||||||
<MudTableSortLabel SortBy="new Func<PCRB,object>(x=>x.InsertTimeStamp)">
|
<MudTableSortLabel SortBy="new Func<PCRB,object>(x=>x.InsertTimeStamp)">
|
||||||
Submitted Date
|
Submitted Date
|
||||||
</MudTableSortLabel>
|
</MudTableSortLabel>
|
||||||
</MudTh>
|
</MudTh>
|
||||||
<MudTh>
|
<MudTh>
|
||||||
<MudTableSortLabel SortBy="new Func<PCRB,object>(x=>x.LastUpdateDate)">
|
<MudTableSortLabel SortBy="new Func<PCRB,object>(x=>x.ClosedDate)">
|
||||||
Last Updated
|
Completed Date
|
||||||
</MudTableSortLabel>
|
</MudTableSortLabel>
|
||||||
</MudTh>
|
</MudTh>
|
||||||
<MudTh>
|
<MudTh>
|
||||||
<MudTableSortLabel SortBy="new Func<PCRB,object>(x=>x.ClosedDate)">
|
<MudTableSortLabel SortBy="new Func<PCRB, object>(x=>(x.FollowUps.FirstOrDefault() is null ?
|
||||||
|
DateTimeUtilities.MIN_DT:
|
||||||
|
x.FollowUps.First().FollowUpDate))">
|
||||||
|
Follow Up Date
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortBy="new Func<PCRB, object>(x=>(x.FollowUps.FirstOrDefault() is null ?
|
||||||
|
DateTimeUtilities.MIN_DT:
|
||||||
|
x.FollowUps.First().CompletedDate))">
|
||||||
Closed Date
|
Closed Date
|
||||||
</MudTableSortLabel>
|
</MudTableSortLabel>
|
||||||
</MudTh>
|
</MudTh>
|
||||||
@ -66,10 +80,20 @@
|
|||||||
</MudTd>
|
</MudTd>
|
||||||
<MudTd DataLabel="Title">@context.Title</MudTd>
|
<MudTd DataLabel="Title">@context.Title</MudTd>
|
||||||
<MudTd DataLabel="Owner">@context.OwnerName</MudTd>
|
<MudTd DataLabel="Owner">@context.OwnerName</MudTd>
|
||||||
|
<MudTd DataLabel="Type">@context.Type</MudTd>
|
||||||
<MudTd DataLabel="Stage">@(GetStageName(context.CurrentStep))</MudTd>
|
<MudTd DataLabel="Stage">@(GetStageName(context.CurrentStep))</MudTd>
|
||||||
<MudTd DataLabel="Submitted Date">@DateTimeUtilities.GetDateAsStringMinDefault(context.InsertTimeStamp)</MudTd>
|
<MudTd DataLabel="Submitted Date">@DateTimeUtilities.GetDateAsStringMinDefault(context.InsertTimeStamp)</MudTd>
|
||||||
<MudTd DataLabel="Last Updated">@DateTimeUtilities.GetDateAsStringMinDefault(context.LastUpdateDate)</MudTd>
|
<MudTd DataLabel="Completed Date">@DateTimeUtilities.GetDateAsStringMaxDefault(context.ClosedDate)</MudTd>
|
||||||
<MudTd DataLabel="Closed Date">@DateTimeUtilities.GetDateAsStringMaxDefault(context.ClosedDate)</MudTd>
|
<MudTd DataLabel="Follow Up Date">@(DateTimeUtilities.GetDateAsStringMaxDefault(context.FollowUps
|
||||||
|
.FirstOrDefault()?.FollowUpDate
|
||||||
|
)
|
||||||
|
)
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="Closed Date">@(DateTimeUtilities.GetDateAsStringMaxDefault(context.FollowUps
|
||||||
|
.FirstOrDefault()?.CompletedDate
|
||||||
|
)
|
||||||
|
)
|
||||||
|
</MudTd>
|
||||||
</RowTemplate>
|
</RowTemplate>
|
||||||
<PagerContent>
|
<PagerContent>
|
||||||
<MudTablePager />
|
<MudTablePager />
|
||||||
@ -80,47 +104,3 @@
|
|||||||
<MudOverlay @bind-Visible=inProcess DarkBackground="true" AutoClose="false">
|
<MudOverlay @bind-Visible=inProcess DarkBackground="true" AutoClose="false">
|
||||||
<MudProgressCircular Color="Color.Info" Size="Size.Large" Indeterminate="true" />
|
<MudProgressCircular Color="Color.Info" Size="Size.Large" Indeterminate="true" />
|
||||||
</MudOverlay>
|
</MudOverlay>
|
||||||
|
|
||||||
@code {
|
|
||||||
private bool inProcess = false;
|
|
||||||
private string searchString = "";
|
|
||||||
private IEnumerable<PCRB> allPCRBs = new List<PCRB>();
|
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync() {
|
|
||||||
inProcess = true;
|
|
||||||
try {
|
|
||||||
if (pcrbService is null) {
|
|
||||||
throw new Exception("PCRB service not injected!");
|
|
||||||
} else {
|
|
||||||
allPCRBs = await pcrbService.GetAllPCRBs(false);
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
snackbar.Add(ex.Message, Severity.Error);
|
|
||||||
}
|
|
||||||
inProcess = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool FilterFuncForTable(PCRB pcrb) => FilterFunc(pcrb, searchString);
|
|
||||||
|
|
||||||
private bool FilterFunc(PCRB pcrb, string searchString) {
|
|
||||||
if (string.IsNullOrWhiteSpace(searchString))
|
|
||||||
return true;
|
|
||||||
if (pcrb.Title.ToLower().Contains(searchString.Trim().ToLower()))
|
|
||||||
return true;
|
|
||||||
if (pcrb.OwnerName.ToLower().Contains(searchString.Trim().ToLower()))
|
|
||||||
return true;
|
|
||||||
if (pcrb.PlanNumber.ToString().Contains(searchString.Trim()))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GoTo(string page) {
|
|
||||||
cache.Set("redirectUrl", page);
|
|
||||||
navigationManager.NavigateTo(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetStageName(int step) {
|
|
||||||
if (step >= PCRB.Stages.Length || step < 0) return "";
|
|
||||||
return PCRB.Stages[step];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
64
MesaFabApproval.Client/Pages/PCRBAll.razor.cs
Normal file
64
MesaFabApproval.Client/Pages/PCRBAll.razor.cs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
using MesaFabApproval.Client.Services;
|
||||||
|
using MesaFabApproval.Shared.Models;
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
|
||||||
|
using MudBlazor;
|
||||||
|
|
||||||
|
namespace MesaFabApproval.Client.Pages;
|
||||||
|
|
||||||
|
public partial class PCRBAll {
|
||||||
|
[Inject] IPCRBService pcrbService { get; set; }
|
||||||
|
[Inject] ISnackbar snackbar { get; set; }
|
||||||
|
[Inject] IMemoryCache cache { get; set; }
|
||||||
|
[Inject] NavigationManager navigationManager { get; set; }
|
||||||
|
|
||||||
|
private bool inProcess = false;
|
||||||
|
private string searchString = "";
|
||||||
|
private IEnumerable<PCRB> allPCRBs = new List<PCRB>();
|
||||||
|
|
||||||
|
protected override async Task OnParametersSetAsync() {
|
||||||
|
inProcess = true;
|
||||||
|
try {
|
||||||
|
cache.Set("redirectUrl", "pcrb/all");
|
||||||
|
|
||||||
|
if (pcrbService is null) {
|
||||||
|
throw new Exception("PCRB service not injected!");
|
||||||
|
} else {
|
||||||
|
allPCRBs = await pcrbService.GetAllPCRBs(false);
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
snackbar.Add(ex.Message, Severity.Error);
|
||||||
|
}
|
||||||
|
inProcess = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool FilterFuncForTable(PCRB pcrb) => FilterFunc(pcrb, searchString);
|
||||||
|
|
||||||
|
private bool FilterFunc(PCRB pcrb, string searchString) {
|
||||||
|
if (string.IsNullOrWhiteSpace(searchString))
|
||||||
|
return true;
|
||||||
|
if (pcrb.Title.ToLower().Contains(searchString.Trim().ToLower()))
|
||||||
|
return true;
|
||||||
|
if (pcrb.OwnerName.ToLower().Contains(searchString.Trim().ToLower()))
|
||||||
|
return true;
|
||||||
|
if (pcrb.Type.ToLower().Contains(searchString.Trim().ToLower()))
|
||||||
|
return true;
|
||||||
|
if (GetStageName(pcrb.CurrentStep).ToLower().Contains(searchString.Trim().ToLower()))
|
||||||
|
return true;
|
||||||
|
if (pcrb.PlanNumber.ToString().Contains(searchString.Trim()))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GoTo(string page) {
|
||||||
|
cache.Set("redirectUrl", page);
|
||||||
|
navigationManager.NavigateTo(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetStageName(int step) {
|
||||||
|
if (step >= PCRB.Stages.Length || step < 0) return "";
|
||||||
|
return PCRB.Stages[step];
|
||||||
|
}
|
||||||
|
}
|
@ -6,20 +6,22 @@
|
|||||||
|
|
||||||
<MudPaper Class="p-2 m-2 d-flex flex-row justify-content-between">
|
<MudPaper Class="p-2 m-2 d-flex flex-row justify-content-between">
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.ChevronLeft"
|
<MudIconButton Icon="@Icons.Material.Filled.ChevronLeft"
|
||||||
Variant="Variant.Outlined"
|
Variant="Variant.Outlined"
|
||||||
Color="Color.Dark"
|
Color="Color.Dark"
|
||||||
OnClick="@ReturnToAllPcrbs"
|
OnClick="@ReturnToAllPcrbs"
|
||||||
Size="Size.Large" />
|
Size="Size.Large" />
|
||||||
<MudText Typo="Typo.h3" Align="Align.Center">PCRB @planNumber</MudText>
|
<MudText Typo="Typo.h3" Align="Align.Center">PCRB @planNumber</MudText>
|
||||||
<MudPaper Height="100%" Width="0.1%" Square="true" />
|
<MudPaper Height="100%" Width="0.1%" Square="true" />
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
|
|
||||||
@if (pcrb is not null) {
|
@if (pcrb is not null) {
|
||||||
<MudTimeline Class="mt-2 pt-2" TimelineOrientation="TimelineOrientation.Horizontal"
|
<MudTimeline Class="mt-2 pt-2" TimelineOrientation="TimelineOrientation.Horizontal"
|
||||||
TimelinePosition="TimelinePosition.Bottom">
|
TimelinePosition="TimelinePosition.Bottom">
|
||||||
@for (int i = 0; i < PCRB.Stages.Length; i++) {
|
@for (int i = 0; i < PCRB.Stages.Length; i++) {
|
||||||
Color color;
|
Color color;
|
||||||
if (pcrb.CurrentStep > i || pcrb.CurrentStep == (PCRB.Stages.Length - 1)) {
|
if (pcrb.CurrentStep > i ||
|
||||||
|
(i == (int)PCRB.StagesEnum.Complete && pcrb.CurrentStep == (int)PCRB.StagesEnum.Complete) ||
|
||||||
|
(i == (int)PCRB.StagesEnum.Closed && pcrb.CurrentStep == (int)PCRB.StagesEnum.Closed)) {
|
||||||
color = Color.Success;
|
color = Color.Success;
|
||||||
} else if (pcrb.CurrentStep == i) {
|
} else if (pcrb.CurrentStep == i) {
|
||||||
color = Color.Info;
|
color = Color.Info;
|
||||||
@ -35,14 +37,14 @@
|
|||||||
}
|
}
|
||||||
</MudTimeline>
|
</MudTimeline>
|
||||||
|
|
||||||
bool pcrbIsSubmitted = pcrb.CurrentStep > 0 && pcrb.InsertTimeStamp > DateTimeUtilities.MIN_DT;
|
bool pcrbIsSubmitted = pcrb.CurrentStep > (int)PCRB.StagesEnum.Draft && pcrb.InsertTimeStamp > DateTimeUtilities.MIN_DT;
|
||||||
bool pcrbIsComplete = pcrb.ClosedDate < DateTimeUtilities.MAX_DT && pcrb.CurrentStep == (PCRB.Stages.Length - 1);
|
bool pcrbIsComplete = pcrb.ClosedDate < DateTimeUtilities.MAX_DT && pcrb.CurrentStep >= (int)PCRB.StagesEnum.Complete;
|
||||||
bool userIsOriginator = pcrb.OwnerID == authStateProvider.CurrentUser?.UserID;
|
bool userIsOriginator = pcrb.OwnerID == authStateProvider.CurrentUser?.UserID;
|
||||||
bool userIsAdmin = authStateProvider.CurrentUser is null ? false : authStateProvider.CurrentUser.IsAdmin;
|
bool userIsAdmin = authStateProvider.CurrentUser is null ? false : authStateProvider.CurrentUser.IsAdmin;
|
||||||
bool userIsApprover = UserIsApprover();
|
bool userIsApprover = UserIsApprover();
|
||||||
|
|
||||||
@if ((!pcrbIsSubmitted && !string.IsNullOrWhiteSpace(pcrb.Title) && (userIsOriginator || userIsAdmin)) ||
|
@if ((!pcrbIsSubmitted && !string.IsNullOrWhiteSpace(pcrb.Title) && (userIsOriginator || userIsAdmin)) ||
|
||||||
(!pcrbIsSubmitted && pcrb.PlanNumber > 0 && (userIsOriginator || userIsAdmin))) {
|
(!pcrbIsSubmitted && pcrb.PlanNumber > 0 && (userIsOriginator || userIsAdmin))) {
|
||||||
<MudPaper Outlined="true"
|
<MudPaper Outlined="true"
|
||||||
Class="p-2 m-2 d-flex flex-wrap gap-3 justify-content-center align-content-center"
|
Class="p-2 m-2 d-flex flex-wrap gap-3 justify-content-center align-content-center"
|
||||||
Elevation="10">
|
Elevation="10">
|
||||||
@ -61,9 +63,9 @@
|
|||||||
}
|
}
|
||||||
@if (!pcrbIsSubmitted && pcrb.PlanNumber > 0 && (userIsOriginator || userIsAdmin)) {
|
@if (!pcrbIsSubmitted && pcrb.PlanNumber > 0 && (userIsOriginator || userIsAdmin)) {
|
||||||
<MudButton Variant="Variant.Filled"
|
<MudButton Variant="Variant.Filled"
|
||||||
Color="Color.Secondary"
|
Color="Color.Secondary"
|
||||||
Disabled="@deleteInProcess"
|
Disabled="@deleteInProcess"
|
||||||
OnClick=DeletePCRB>
|
OnClick=DeletePCRB>
|
||||||
@if (deleteInProcess) {
|
@if (deleteInProcess) {
|
||||||
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
||||||
<MudText>Processing</MudText>
|
<MudText>Processing</MudText>
|
||||||
@ -91,114 +93,114 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
<MudPaper Outlined="true"
|
<MudPaper Outlined="true"
|
||||||
Class="p-2 m-2 d-flex flex-wrap gap-3 justify-content-center align-content-start"
|
Class="p-2 m-2 d-flex flex-wrap gap-3 justify-content-center align-content-start"
|
||||||
Elevation="10">
|
Elevation="10">
|
||||||
<MudTextField @bind-Value=pcrb.PlanNumber
|
<MudTextField @bind-Value=pcrb.PlanNumber
|
||||||
Text="@pcrb.PlanNumber.ToString()"
|
Text="@pcrb.PlanNumber.ToString()"
|
||||||
T="int"
|
T="int"
|
||||||
Disabled="true"
|
Disabled="true"
|
||||||
Label="Change#"
|
Label="Change#"
|
||||||
Required
|
Required
|
||||||
Variant="Variant.Outlined" />
|
Variant="Variant.Outlined" />
|
||||||
<MudTextField @bind-Value=pcrb.Title
|
<MudTextField @bind-Value=pcrb.Title
|
||||||
Text="@pcrb.Title"
|
Text="@pcrb.Title"
|
||||||
Disabled="@(pcrbIsSubmitted)"
|
Disabled="@(pcrbIsSubmitted)"
|
||||||
T="string"
|
T="string"
|
||||||
AutoGrow
|
AutoGrow
|
||||||
AutoFocus
|
AutoFocus
|
||||||
Immediate
|
Immediate
|
||||||
Clearable
|
Clearable
|
||||||
Required
|
Required
|
||||||
Variant="Variant.Outlined"
|
Variant="Variant.Outlined"
|
||||||
Label="Project Name" />
|
Label="Project Name" />
|
||||||
<MudSelect T="User"
|
<MudSelect T="User"
|
||||||
Label="Originator"
|
Label="Originator"
|
||||||
Variant="Variant.Outlined"
|
Variant="Variant.Outlined"
|
||||||
Required
|
Required
|
||||||
Clearable
|
Clearable
|
||||||
AnchorOrigin="Origin.BottomCenter"
|
AnchorOrigin="Origin.BottomCenter"
|
||||||
ToStringFunc="@UserToNameConverter"
|
ToStringFunc="@UserToNameConverter"
|
||||||
Disabled=@(pcrbIsSubmitted)
|
Disabled=@(pcrbIsSubmitted)
|
||||||
@bind-Value=@selectedOwner>
|
@bind-Value=@selectedOwner>
|
||||||
@foreach (User user in allActiveUsers.OrderBy(u => u.LastName)) {
|
@foreach (User user in allActiveUsers.OrderBy(u => u.LastName)) {
|
||||||
<MudSelectItem T="User" Value="@(user)" />
|
<MudSelectItem T="User" Value="@(user)" />
|
||||||
}
|
}
|
||||||
</MudSelect>
|
</MudSelect>
|
||||||
<MudSelect T="string"
|
<MudSelect T="string"
|
||||||
Variant="Variant.Outlined"
|
Variant="Variant.Outlined"
|
||||||
Required
|
Required
|
||||||
Clearable
|
Clearable
|
||||||
AnchorOrigin="Origin.BottomCenter"
|
AnchorOrigin="Origin.BottomCenter"
|
||||||
Disabled="@pcrbIsSubmitted"
|
Disabled="@pcrbIsSubmitted"
|
||||||
@bind-Value="@pcrb.ChangeLevel"
|
@bind-Value="@pcrb.ChangeLevel"
|
||||||
Text="@pcrb.ChangeLevel"
|
Text="@pcrb.ChangeLevel"
|
||||||
Label="Change Level">
|
Label="Change Level">
|
||||||
<MudSelectItem Value="@("Global - Class 1")" />
|
<MudSelectItem Value="@("Global - Class 1")" />
|
||||||
<MudSelectItem Value="@("Other Site + Mesa - Class 2")" />
|
<MudSelectItem Value="@("Other Site + Mesa - Class 2")" />
|
||||||
<MudSelectItem Value="@("Mesa - Class 3")" />
|
<MudSelectItem Value="@("Mesa - Class 3")" />
|
||||||
</MudSelect>
|
</MudSelect>
|
||||||
<MudSelect T="string"
|
<MudSelect T="string"
|
||||||
Variant="Variant.Outlined"
|
Variant="Variant.Outlined"
|
||||||
Required
|
Required
|
||||||
Clearable
|
Clearable
|
||||||
AnchorOrigin="Origin.BottomCenter"
|
AnchorOrigin="Origin.BottomCenter"
|
||||||
Disabled="@pcrbIsSubmitted"
|
Disabled="@pcrbIsSubmitted"
|
||||||
@bind-Value="@pcrb.Type"
|
@bind-Value="@pcrb.Type"
|
||||||
Text="@pcrb.Type"
|
Text="@pcrb.Type"
|
||||||
Label="Change Type">
|
Label="Change Type">
|
||||||
<MudSelectItem Value="@("Cost Savings")" />
|
<MudSelectItem Value="@("Cost Savings")" />
|
||||||
<MudSelectItem Value="@("Process Efficiency")" />
|
<MudSelectItem Value="@("Process Efficiency")" />
|
||||||
<MudSelectItem Value="@("Process Improvement")" />
|
<MudSelectItem Value="@("Process Improvement")" />
|
||||||
<MudSelectItem Value="@("Business Continuity")" />
|
<MudSelectItem Value="@("Business Continuity")" />
|
||||||
</MudSelect>
|
</MudSelect>
|
||||||
<MudCheckBox Disabled="@pcrbIsSubmitted"
|
<MudCheckBox Disabled="@pcrbIsSubmitted"
|
||||||
Color="Color.Tertiary"
|
Color="Color.Tertiary"
|
||||||
@bind-Value=pcrb.IsITAR
|
@bind-Value=pcrb.IsITAR
|
||||||
Label="Export Controlled"
|
Label="Export Controlled"
|
||||||
LabelPosition="LabelPosition.Start" />
|
LabelPosition="LabelPosition.Start" />
|
||||||
<MudTextField Disabled="true"
|
<MudTextField Disabled="true"
|
||||||
T="string"
|
T="string"
|
||||||
Value="@DateTimeUtilities.GetDateAsStringMinDefault(pcrb.InsertTimeStamp)"
|
Value="@DateTimeUtilities.GetDateAsStringMinDefault(pcrb.InsertTimeStamp)"
|
||||||
Label="Submit Date"
|
Label="Submit Date"
|
||||||
Variant="Variant.Outlined" />
|
Variant="Variant.Outlined" />
|
||||||
<MudTextField Disabled="true"
|
<MudTextField Disabled="true"
|
||||||
T="string"
|
T="string"
|
||||||
Value="@DateTimeUtilities.GetDateAsStringMinDefault(pcrb.LastUpdateDate)"
|
Value="@DateTimeUtilities.GetDateAsStringMinDefault(pcrb.LastUpdateDate)"
|
||||||
Label="Last Update"
|
Label="Last Update"
|
||||||
Variant="Variant.Outlined" />
|
Variant="Variant.Outlined" />
|
||||||
<MudTextField Disabled="true"
|
<MudTextField Disabled="true"
|
||||||
T="string"
|
T="string"
|
||||||
Value="@DateTimeUtilities.GetDateAsStringMaxDefault(pcrb.ClosedDate)"
|
Value="@DateTimeUtilities.GetDateAsStringMaxDefault(pcrb.ClosedDate)"
|
||||||
Label="Complete Date"
|
Label="Complete Date"
|
||||||
Variant="Variant.Outlined" />
|
Variant="Variant.Outlined" />
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
|
|
||||||
<MudPaper Outlined="true"
|
<MudPaper Outlined="true"
|
||||||
Class="p-2 m-2 d-flex flex-wrap gap-3 justify-content-center align-content-start"
|
Class="p-2 m-2 d-flex flex-wrap gap-3 justify-content-center align-content-start"
|
||||||
Elevation="10">
|
Elevation="10">
|
||||||
<MudTextField @bind-Value=pcrb.ChangeDescription
|
<MudTextField @bind-Value=pcrb.ChangeDescription
|
||||||
Text="@pcrb.ChangeDescription"
|
Text="@pcrb.ChangeDescription"
|
||||||
Disabled="@(pcrbIsSubmitted)"
|
Disabled="@(pcrbIsSubmitted)"
|
||||||
T="string"
|
T="string"
|
||||||
AutoGrow
|
AutoGrow
|
||||||
Immediate
|
Immediate
|
||||||
Clearable
|
Clearable
|
||||||
Required
|
Required
|
||||||
Variant="Variant.Outlined"
|
Variant="Variant.Outlined"
|
||||||
Label="Description Of Change" />
|
Label="Description Of Change" />
|
||||||
<MudTextField @bind-Value=pcrb.ReasonForChange
|
<MudTextField @bind-Value=pcrb.ReasonForChange
|
||||||
Text="@pcrb.ReasonForChange"
|
Text="@pcrb.ReasonForChange"
|
||||||
Disabled="@(pcrbIsSubmitted)"
|
Disabled="@(pcrbIsSubmitted)"
|
||||||
T="string"
|
T="string"
|
||||||
AutoGrow
|
AutoGrow
|
||||||
Immediate
|
Immediate
|
||||||
Clearable
|
Clearable
|
||||||
Required
|
Required
|
||||||
Variant="Variant.Outlined"
|
Variant="Variant.Outlined"
|
||||||
Label="Reason For Change" />
|
Label="Reason For Change" />
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
|
|
||||||
@if (pcrb.PlanNumber > 0 && pcrb.CurrentStep > 0) {
|
@if (pcrb.PlanNumber > 0 && pcrb.CurrentStep > (int)PCRB.StagesEnum.Draft) {
|
||||||
<MudExpansionPanels MultiExpansion="true">
|
<MudExpansionPanels MultiExpansion="true">
|
||||||
@for (int i = 1; i < 4; i++) {
|
@for (int i = 1; i < 4; i++) {
|
||||||
int current_i = i;
|
int current_i = i;
|
||||||
@ -229,7 +231,7 @@
|
|||||||
int currentStagePendingApprovalsCount = currentStageApprovals.Where(a => a.ItemStatus == 0 && a.AssignedDate > DateTimeUtilities.MIN_DT).Count();
|
int currentStagePendingApprovalsCount = currentStageApprovals.Where(a => a.ItemStatus == 0 && a.AssignedDate > DateTimeUtilities.MIN_DT).Count();
|
||||||
int currentStageApprovedApprovalsCount = currentStageApprovals.Where(a => a.ItemStatus == 1).Count();
|
int currentStageApprovedApprovalsCount = currentStageApprovals.Where(a => a.ItemStatus == 1).Count();
|
||||||
int currentStageDeniedApprovalsCount = currentStageApprovals.Where(a => a.ItemStatus == -1).Count();
|
int currentStageDeniedApprovalsCount = currentStageApprovals.Where(a => a.ItemStatus == -1).Count();
|
||||||
|
|
||||||
bool currentStageApproved = currentStageApprovedApprovalsCount >= 4 && currentStageUnsubmittedApprovalCount == 0 &&
|
bool currentStageApproved = currentStageApprovedApprovalsCount >= 4 && currentStageUnsubmittedApprovalCount == 0 &&
|
||||||
currentStagePendingApprovalsCount == 0;
|
currentStagePendingApprovalsCount == 0;
|
||||||
bool currentStageSubmitted = (currentStageApprovals.Count() > 0 && currentStagePendingApprovalsCount > 0 &&
|
bool currentStageSubmitted = (currentStageApprovals.Count() > 0 && currentStagePendingApprovalsCount > 0 &&
|
||||||
@ -260,7 +262,7 @@
|
|||||||
<TitleContent>
|
<TitleContent>
|
||||||
<MudText Typo="Typo.h4" Align="Align.Center">@($"PCR {current_i}")</MudText>
|
<MudText Typo="Typo.h4" Align="Align.Center">@($"PCR {current_i}")</MudText>
|
||||||
@if (previousStageSubmitted && (attachmentsMissing || actionItemsIncomplete ||
|
@if (previousStageSubmitted && (attachmentsMissing || actionItemsIncomplete ||
|
||||||
affectedDocumentsIncomplete || approvalsIncomplete)) {
|
affectedDocumentsIncomplete || approvalsIncomplete)) {
|
||||||
StringBuilder sb = new();
|
StringBuilder sb = new();
|
||||||
int missingSectionCount = 0;
|
int missingSectionCount = 0;
|
||||||
sb.Append("Incomplete sections: ");
|
sb.Append("Incomplete sections: ");
|
||||||
@ -299,31 +301,31 @@
|
|||||||
</TitleContent>
|
</TitleContent>
|
||||||
<ChildContent>
|
<ChildContent>
|
||||||
<MudPaper Outlined="true"
|
<MudPaper Outlined="true"
|
||||||
Class="p-2 m-2 d-flex flex-column justify-start">
|
Class="p-2 m-2 d-flex flex-column justify-start">
|
||||||
|
|
||||||
<MudText Typo="Typo.h5" Align="Align.Center">Supporting Documents</MudText>
|
<MudText Typo="Typo.h5" Align="Align.Center">Supporting Documents</MudText>
|
||||||
|
|
||||||
<MudTable Items="@attachments.Where(a => a.Step == current_i)"
|
<MudTable Items="@attachments.Where(a => a.Step == current_i)"
|
||||||
Class="m-2"
|
Class="m-2"
|
||||||
Striped="true"
|
Striped="true"
|
||||||
SortLabel="Sort By"
|
SortLabel="Sort By"
|
||||||
Hover="true">
|
Hover="true">
|
||||||
<ToolBarContent>
|
<ToolBarContent>
|
||||||
<MudStack Row="true" Justify="Justify.Center" Spacing="1" Style="width: 100%">
|
<MudStack Row="true" Justify="Justify.Center" Spacing="1" Style="width: 100%">
|
||||||
@if (pcrb.ClosedDate >= DateTimeUtilities.MAX_DT && previousStageSubmitted && !currentStageSubmitted) {
|
@if (pcrb.ClosedDate >= DateTimeUtilities.MAX_DT && previousStageSubmitted && !currentStageSubmitted) {
|
||||||
@if (current_i == 1) {
|
@if (current_i == 1) {
|
||||||
<MudButton Variant="Variant.Filled"
|
<MudButton Variant="Variant.Filled"
|
||||||
Color="Color.Tertiary"
|
Color="Color.Tertiary"
|
||||||
Href="https://plm.intra.infineon.com/Windchill/netmarkets/jsp/ext/infineon/dcoidreleased.jsp?obid=OR:wt.doc.WTDocument:1477717325"
|
Href="https://plm.intra.infineon.com/Windchill/netmarkets/jsp/ext/infineon/dcoidreleased.jsp?obid=OR:wt.doc.WTDocument:1477717325"
|
||||||
Target="_blank">
|
Target="_blank">
|
||||||
Download PCRB Template
|
Download PCRB Template
|
||||||
</MudButton>
|
</MudButton>
|
||||||
}
|
}
|
||||||
<MudButton Variant="Variant.Filled"
|
<MudButton Variant="Variant.Filled"
|
||||||
Color="Color.Tertiary"
|
Color="Color.Tertiary"
|
||||||
OnClick="@((e) => UploadAttachment(current_i))"
|
OnClick="@((e) => UploadAttachment(current_i))"
|
||||||
Disabled="@attachmentUploadInProcess"
|
Disabled="@attachmentUploadInProcess"
|
||||||
StartIcon="@Icons.Material.Filled.AttachFile">
|
StartIcon="@Icons.Material.Filled.AttachFile">
|
||||||
@if (attachmentUploadInProcess) {
|
@if (attachmentUploadInProcess) {
|
||||||
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
||||||
<MudText>Processing</MudText>
|
<MudText>Processing</MudText>
|
||||||
@ -354,8 +356,8 @@
|
|||||||
<RowTemplate>
|
<RowTemplate>
|
||||||
<MudTd DataLabel="File Name">
|
<MudTd DataLabel="File Name">
|
||||||
<a href="@(@$"{config["FabApprovalApiBaseUrl"]}/pcrb/attachmentFile?path={context.Path}&fileName={context.FileName}")"
|
<a href="@(@$"{config["FabApprovalApiBaseUrl"]}/pcrb/attachmentFile?path={context.Path}&fileName={context.FileName}")"
|
||||||
download="@(context.FileName)"
|
download="@(context.FileName)"
|
||||||
target="_top">
|
target="_top">
|
||||||
@context.FileName
|
@context.FileName
|
||||||
</a>
|
</a>
|
||||||
</MudTd>
|
</MudTd>
|
||||||
@ -364,9 +366,9 @@
|
|||||||
@if (pcrb.ClosedDate >= DateTimeUtilities.MAX_DT && previousStageSubmitted && !currentStageSubmitted) {
|
@if (pcrb.ClosedDate >= DateTimeUtilities.MAX_DT && previousStageSubmitted && !currentStageSubmitted) {
|
||||||
<MudTd Style="text-align:center;">
|
<MudTd Style="text-align:center;">
|
||||||
<MudButton Color="Color.Secondary"
|
<MudButton Color="Color.Secondary"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
Disabled="@deleteAttachmentInProcess"
|
Disabled="@deleteAttachmentInProcess"
|
||||||
OnClick="@((e) => DeleteAttachment(context))">
|
OnClick="@((e) => DeleteAttachment(context))">
|
||||||
@if (deleteAttachmentInProcess) {
|
@if (deleteAttachmentInProcess) {
|
||||||
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
||||||
<MudText>Deleting</MudText>
|
<MudText>Deleting</MudText>
|
||||||
@ -389,24 +391,24 @@
|
|||||||
</MudText>
|
</MudText>
|
||||||
}
|
}
|
||||||
<MudTable Items="@actionItems.Where(a => a.Step == current_i)"
|
<MudTable Items="@actionItems.Where(a => a.Step == current_i)"
|
||||||
Class="m-2"
|
Class="m-2"
|
||||||
Striped="true"
|
Striped="true"
|
||||||
SortLabel="Sort By"
|
SortLabel="Sort By"
|
||||||
Hover="true">
|
Hover="true">
|
||||||
<ToolBarContent>
|
<ToolBarContent>
|
||||||
<MudStack Row="true" Justify="Justify.Center" Spacing="1" Style="width: 100%">
|
<MudStack Row="true" Justify="Justify.Center" Spacing="1" Style="width: 100%">
|
||||||
@if (previousStageSubmitted && !currentStageSubmitted) {
|
@if (previousStageSubmitted && !currentStageSubmitted) {
|
||||||
<MudButton Variant="Variant.Filled"
|
<MudButton Variant="Variant.Filled"
|
||||||
Color="Color.Tertiary"
|
Color="Color.Tertiary"
|
||||||
OnClick="@((e) => CreateNewActionItem(current_i))">
|
OnClick="@((e) => CreateNewActionItem(current_i))">
|
||||||
<MudText>New Action Item</MudText>
|
<MudText>New Action Item</MudText>
|
||||||
</MudButton>
|
</MudButton>
|
||||||
}
|
}
|
||||||
@if (currentStagePendingActionItemCount > 0) {
|
@if (currentStagePendingActionItemCount > 0) {
|
||||||
<MudButton Variant="Variant.Filled"
|
<MudButton Variant="Variant.Filled"
|
||||||
Color="Color.Tertiary"
|
Color="Color.Tertiary"
|
||||||
Disabled="@processing"
|
Disabled="@processing"
|
||||||
OnClick="@((e) => CloseAllActionItems(current_i))">
|
OnClick="@((e) => CloseAllActionItems(current_i))">
|
||||||
<MudText>Complete All Actions</MudText>
|
<MudText>Complete All Actions</MudText>
|
||||||
</MudButton>
|
</MudButton>
|
||||||
}
|
}
|
||||||
@ -448,14 +450,14 @@
|
|||||||
@if (pcrb.ClosedDate >= DateTimeUtilities.MAX_DT && context.ClosedByID == 0) {
|
@if (pcrb.ClosedDate >= DateTimeUtilities.MAX_DT && context.ClosedByID == 0) {
|
||||||
<MudTd Style="text-align:center;">
|
<MudTd Style="text-align:center;">
|
||||||
<MudButton Color="Color.Tertiary"
|
<MudButton Color="Color.Tertiary"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
OnClick="@((e) => UpdateActionItem(context))">
|
OnClick="@((e) => UpdateActionItem(context))">
|
||||||
<MudText>Update</MudText>
|
<MudText>Update</MudText>
|
||||||
</MudButton>
|
</MudButton>
|
||||||
@if (!currentStageSubmitted) {
|
@if (!currentStageSubmitted) {
|
||||||
<MudButton Color="Color.Secondary"
|
<MudButton Color="Color.Secondary"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
OnClick="@((e) => DeleteActionItem(context))">
|
OnClick="@((e) => DeleteActionItem(context))">
|
||||||
<MudText>Delete</MudText>
|
<MudText>Delete</MudText>
|
||||||
</MudButton>
|
</MudButton>
|
||||||
}
|
}
|
||||||
@ -468,10 +470,10 @@
|
|||||||
|
|
||||||
<MudText Typo="Typo.h5" Align="Align.Center">Affected Documents</MudText>
|
<MudText Typo="Typo.h5" Align="Align.Center">Affected Documents</MudText>
|
||||||
<MudTable Items="@pcr3Documents"
|
<MudTable Items="@pcr3Documents"
|
||||||
Class="m-2"
|
Class="m-2"
|
||||||
Striped="true"
|
Striped="true"
|
||||||
SortLabel="Sort By"
|
SortLabel="Sort By"
|
||||||
Hover="true">
|
Hover="true">
|
||||||
<HeaderContent>
|
<HeaderContent>
|
||||||
<MudTh>
|
<MudTh>
|
||||||
<MudTableSortLabel SortBy="new Func<PCR3Document, object>(x=>x.DocType)">
|
<MudTableSortLabel SortBy="new Func<PCR3Document, object>(x=>x.DocType)">
|
||||||
@ -513,8 +515,8 @@
|
|||||||
context.GetEcnNumberString();
|
context.GetEcnNumberString();
|
||||||
} else {
|
} else {
|
||||||
<MudLink
|
<MudLink
|
||||||
Href=@($"{config["OldFabApprovalUrl"]}/ECN/Edit?IssueID={context.GetEcnNumberString()}")
|
Href=@($"{config["OldFabApprovalUrl"]}/ECN/Edit?IssueID={context.GetEcnNumberString()}")
|
||||||
Target="_blank">
|
Target="_blank">
|
||||||
@context.GetEcnNumberString()
|
@context.GetEcnNumberString()
|
||||||
</MudLink>
|
</MudLink>
|
||||||
}
|
}
|
||||||
@ -526,8 +528,8 @@
|
|||||||
@if (pcrb.ClosedDate >= DateTimeUtilities.MAX_DT && !currentStageSubmitted) {
|
@if (pcrb.ClosedDate >= DateTimeUtilities.MAX_DT && !currentStageSubmitted) {
|
||||||
<MudTd Style="text-align:center;">
|
<MudTd Style="text-align:center;">
|
||||||
<MudButton Color="Color.Tertiary"
|
<MudButton Color="Color.Tertiary"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
OnClick="@((e) => UpdatePCR3Document(context))">
|
OnClick="@((e) => UpdatePCR3Document(context))">
|
||||||
<MudText>Update</MudText>
|
<MudText>Update</MudText>
|
||||||
</MudButton>
|
</MudButton>
|
||||||
</MudTd>
|
</MudTd>
|
||||||
@ -539,23 +541,23 @@
|
|||||||
<MudDivider DividerType="DividerType.Middle" Class="my-1" />
|
<MudDivider DividerType="DividerType.Middle" Class="my-1" />
|
||||||
<MudText Typo="Typo.h5" Align="Align.Center">Attendees</MudText>
|
<MudText Typo="Typo.h5" Align="Align.Center">Attendees</MudText>
|
||||||
<MudTable Items="@attendees.Where(a => a.Step == current_i)"
|
<MudTable Items="@attendees.Where(a => a.Step == current_i)"
|
||||||
Class="m-2"
|
Class="m-2"
|
||||||
Striped="true"
|
Striped="true"
|
||||||
SortLabel="Sort By"
|
SortLabel="Sort By"
|
||||||
Hover="true">
|
Hover="true">
|
||||||
<ToolBarContent>
|
<ToolBarContent>
|
||||||
@if (pcrb.ClosedDate >= DateTimeUtilities.MAX_DT && !currentStageSubmitted) {
|
@if (pcrb.ClosedDate >= DateTimeUtilities.MAX_DT && !currentStageSubmitted) {
|
||||||
<MudStack Row="true" Justify="Justify.Center" Spacing="1" Style="width: 100%">
|
<MudStack Row="true" Justify="Justify.Center" Spacing="1" Style="width: 100%">
|
||||||
<MudButton Color="Color.Tertiary"
|
<MudButton Color="Color.Tertiary"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
Class="m-1"
|
Class="m-1"
|
||||||
OnClick="@((e) => AddAttendee(current_i))">
|
OnClick="@((e) => AddAttendee(current_i))">
|
||||||
<MudText>Add Attendee</MudText>
|
<MudText>Add Attendee</MudText>
|
||||||
</MudButton>
|
</MudButton>
|
||||||
<MudButton Color="Color.Tertiary"
|
<MudButton Color="Color.Tertiary"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
Class="m-1"
|
Class="m-1"
|
||||||
OnClick="@((e) => MarkAllAttended(current_i))">
|
OnClick="@((e) => MarkAllAttended(current_i))">
|
||||||
<MudText>Mark All Attended</MudText>
|
<MudText>Mark All Attended</MudText>
|
||||||
</MudButton>
|
</MudButton>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
@ -577,9 +579,9 @@
|
|||||||
</MudTd>
|
</MudTd>
|
||||||
<MudTd DataLabel="Attended?">
|
<MudTd DataLabel="Attended?">
|
||||||
<MudIconButton Disabled="@(pcrb.ClosedDate < DateTimeUtilities.MAX_DT || currentStageSubmitted)"
|
<MudIconButton Disabled="@(pcrb.ClosedDate < DateTimeUtilities.MAX_DT || currentStageSubmitted)"
|
||||||
Icon="@(context.Attended ? Icons.Material.Filled.CheckBox : Icons.Material.Filled.CheckBoxOutlineBlank)"
|
Icon="@(context.Attended ? Icons.Material.Filled.CheckBox : Icons.Material.Filled.CheckBoxOutlineBlank)"
|
||||||
Color="Color.Tertiary"
|
Color="Color.Tertiary"
|
||||||
OnClick="@((e) => MarkAttended(context))" />
|
OnClick="@((e) => MarkAttended(context))" />
|
||||||
</MudTd>
|
</MudTd>
|
||||||
</RowTemplate>
|
</RowTemplate>
|
||||||
</MudTable>
|
</MudTable>
|
||||||
@ -592,33 +594,33 @@
|
|||||||
</MudText>
|
</MudText>
|
||||||
}
|
}
|
||||||
<MudTable Items="@approvals.Where(a => a.Step == current_i).OrderBy(a => a.CompletedDate)"
|
<MudTable Items="@approvals.Where(a => a.Step == current_i).OrderBy(a => a.CompletedDate)"
|
||||||
Class="m-2"
|
Class="m-2"
|
||||||
Striped="true"
|
Striped="true"
|
||||||
SortLabel="Sort By"
|
SortLabel="Sort By"
|
||||||
Hover="true">
|
Hover="true">
|
||||||
<ToolBarContent>
|
<ToolBarContent>
|
||||||
@if (pcrb.ClosedDate >= DateTimeUtilities.MAX_DT && previousStageApproved) {
|
@if (pcrb.ClosedDate >= DateTimeUtilities.MAX_DT && previousStageApproved) {
|
||||||
<MudStack Row="true" Justify="Justify.Center" Spacing="1" Style="width: 100%">
|
<MudStack Row="true" Justify="Justify.Center" Spacing="1" Style="width: 100%">
|
||||||
@if (!currentStageSubmitted) {
|
@if (!currentStageSubmitted) {
|
||||||
<MudButton Variant="Variant.Filled"
|
<MudButton Variant="Variant.Filled"
|
||||||
Color="Color.Tertiary"
|
Color="Color.Tertiary"
|
||||||
OnClick="@((e) => AddApprover(current_i))">
|
OnClick="@((e) => AddApprover(current_i))">
|
||||||
<MudText>Add Approver</MudText>
|
<MudText>Add Approver</MudText>
|
||||||
</MudButton>
|
</MudButton>
|
||||||
}
|
}
|
||||||
@if (previousStageSubmitted && !currentStageSubmitted && currentStageAttachments.Count() > 0 &&
|
@if (previousStageSubmitted && !currentStageSubmitted && currentStageAttachments.Count() > 0 &&
|
||||||
!affectedDocumentsIncomplete && allActionItemsComplete &&
|
!affectedDocumentsIncomplete && allActionItemsComplete &&
|
||||||
!previousStageHasOpenGatedActionItems && atLeastOneAttendeeAttended) {
|
!previousStageHasOpenGatedActionItems && atLeastOneAttendeeAttended) {
|
||||||
@if (submitInProcess) {
|
@if (submitInProcess) {
|
||||||
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
||||||
<MudText>Submitting</MudText>
|
<MudText>Submitting</MudText>
|
||||||
} else {
|
} else {
|
||||||
<MudButton Variant="Variant.Filled"
|
<MudButton Variant="Variant.Filled"
|
||||||
Color="Color.Tertiary"
|
Color="Color.Tertiary"
|
||||||
Disabled="@submitInProcess"
|
Disabled="@submitInProcess"
|
||||||
OnClick="@((e) => SubmitForApproval(current_i))">
|
OnClick="@((e) => SubmitForApproval(current_i))">
|
||||||
<MudText>Submit For Approval</MudText>
|
<MudText>Submit For Approval</MudText>
|
||||||
</MudButton>
|
</MudButton>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</MudStack>
|
</MudStack>
|
||||||
@ -652,31 +654,31 @@
|
|||||||
<MudTd DataLabel="Disposition Date">@DateTimeUtilities.GetDateAsStringMaxDefault(context.CompletedDate)</MudTd>
|
<MudTd DataLabel="Disposition Date">@DateTimeUtilities.GetDateAsStringMaxDefault(context.CompletedDate)</MudTd>
|
||||||
<MudTd DataLabel="Comments">@context.Comments</MudTd>
|
<MudTd DataLabel="Comments">@context.Comments</MudTd>
|
||||||
@if (pcrb.ClosedDate >= DateTimeUtilities.MAX_DT && (currentStageUnsubmittedApprovalCount > 0 ||
|
@if (pcrb.ClosedDate >= DateTimeUtilities.MAX_DT && (currentStageUnsubmittedApprovalCount > 0 ||
|
||||||
currentStagePendingApprovalsCount > 0)) {
|
currentStagePendingApprovalsCount > 0)) {
|
||||||
<MudTd Style="text-align:center;">
|
<MudTd Style="text-align:center;">
|
||||||
@if (context.ItemStatus == 0 && userIsAdmin) {
|
@if (context.ItemStatus == 0 && userIsAdmin) {
|
||||||
<MudButton Color="Color.Warning"
|
<MudButton Color="Color.Warning"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
Class="m-1"
|
Class="m-1"
|
||||||
OnClick="@((e) => UpdateApproval(context))">
|
OnClick="@((e) => UpdateApproval(context))">
|
||||||
<MudText>Update</MudText>
|
<MudText>Update</MudText>
|
||||||
</MudButton>
|
</MudButton>
|
||||||
}
|
}
|
||||||
@if ((current_i < 3 || pcr3Documents.Where(d=>d.CompletedByID == 0).Count() == 0) &&
|
@if ((current_i < 3 || pcr3Documents.Where(d=>d.CompletedByID == 0).Count() == 0) &&
|
||||||
(authStateProvider.CurrentUser is not null && context.UserID == authStateProvider.CurrentUser.UserID) &&
|
(authStateProvider.CurrentUser is not null && context.UserID == authStateProvider.CurrentUser.UserID) &&
|
||||||
context.ItemStatus == 0 && context.AssignedDate > DateTimeUtilities.MIN_DT) {
|
context.ItemStatus == 0 && context.AssignedDate > DateTimeUtilities.MIN_DT) {
|
||||||
<MudButton Color="Color.Tertiary"
|
<MudButton Color="Color.Tertiary"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
Class="m-1"
|
Class="m-1"
|
||||||
Disabled="@processing"
|
Disabled="@processing"
|
||||||
OnClick="@((e) => ApprovePCR(current_i))">
|
OnClick="@((e) => ApprovePCR(current_i))">
|
||||||
<MudText>Approve</MudText>
|
<MudText>Approve</MudText>
|
||||||
</MudButton>
|
</MudButton>
|
||||||
<MudButton Color="Color.Secondary"
|
<MudButton Color="Color.Secondary"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
Class="m-1"
|
Class="m-1"
|
||||||
Disabled="@processing"
|
Disabled="@processing"
|
||||||
OnClick="@((e) => DenyPCR(current_i))">
|
OnClick="@((e) => DenyPCR(current_i))">
|
||||||
<MudText>Deny</MudText>
|
<MudText>Deny</MudText>
|
||||||
</MudButton>
|
</MudButton>
|
||||||
}
|
}
|
||||||
@ -688,6 +690,195 @@
|
|||||||
</ChildContent>
|
</ChildContent>
|
||||||
</MudExpansionPanel>
|
</MudExpansionPanel>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@if (pcrb.FollowUps.Count() > 0) {
|
||||||
|
<MudExpansionPanel Class="m-2" Expanded=@(pcrb.CurrentStep == (int)PCRB.StagesEnum.FollowUp &&
|
||||||
|
!pcrb.FollowUps.First().IsComplete)>
|
||||||
|
<TitleContent>
|
||||||
|
<MudText Typo="Typo.h4" Align="Align.Center">Follow Up</MudText>
|
||||||
|
</TitleContent>
|
||||||
|
<ChildContent>
|
||||||
|
<MudPaper Outlined="true"
|
||||||
|
Class="p-2 m-2 d-flex flex-column justify-start gap-2">
|
||||||
|
<MudPaper Outlined="true"
|
||||||
|
Class="p-1"
|
||||||
|
Elevation="15">
|
||||||
|
<MudText Typo="Typo.h5" Align="Align.Center">Supporting Documents</MudText>
|
||||||
|
<MudTable Items="@attachments.Where(a => a.Step == 5)"
|
||||||
|
Class="m-2"
|
||||||
|
Striped="true"
|
||||||
|
SortLabel="Sort By"
|
||||||
|
Hover="true">
|
||||||
|
<ToolBarContent>
|
||||||
|
<MudStack Row="true" Justify="Justify.Center" Spacing="1" Style="width: 100%">
|
||||||
|
@if (!pcrb.FollowUps.First().IsComplete && !pcrb.FollowUps.First().IsPendingApproval) {
|
||||||
|
<MudButton Variant="Variant.Filled"
|
||||||
|
Color="Color.Tertiary"
|
||||||
|
OnClick="@((e) => UploadAttachment(5))"
|
||||||
|
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>
|
||||||
|
}
|
||||||
|
@if (!pcrb.FollowUps.First().IsPendingApproval && !pcrb.FollowUps.First().IsComplete &&
|
||||||
|
attachments.Where(a => a.Step == 5).Count() > 0 &&
|
||||||
|
approvals.Where(a => a.Step == 5 &&
|
||||||
|
a.UserID == authStateProvider.CurrentUser.UserID &&
|
||||||
|
a.ItemStatus == 0).Count() > 0) {
|
||||||
|
<MudButton Variant="Variant.Filled"
|
||||||
|
Color="Color.Tertiary"
|
||||||
|
OnClick="SubmitFollowUpForApproval"
|
||||||
|
Disabled="@followUpSubmitInProcess">
|
||||||
|
@if (followUpSubmitInProcess) {
|
||||||
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
||||||
|
<MudText>Processing</MudText>
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
<MudText>Submit For Closure</MudText>
|
||||||
|
}
|
||||||
|
</MudButton>
|
||||||
|
}
|
||||||
|
@if (pcrb.FollowUps.First().IsPendingApproval && !pcrb.FollowUps.First().IsComplete &&
|
||||||
|
attachments.Where(a => a.Step == 5).Count() > 0 &&
|
||||||
|
approvals.Where(a => a.Step == 5 &&
|
||||||
|
a.UserID == authStateProvider.CurrentUser.UserID).Count() > 0)
|
||||||
|
{
|
||||||
|
@if (userIsQA) {
|
||||||
|
<MudButton Variant="Variant.Filled"
|
||||||
|
Color="Color.Tertiary"
|
||||||
|
OnClick="ApproveFollowUp"
|
||||||
|
Disabled="@followUpApproveInProcess">
|
||||||
|
@if (followUpApproveInProcess) {
|
||||||
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
||||||
|
<MudText>Processing</MudText>
|
||||||
|
} else {
|
||||||
|
<MudText>Close</MudText>
|
||||||
|
}
|
||||||
|
</MudButton>
|
||||||
|
<MudButton Variant="Variant.Filled"
|
||||||
|
Color="Color.Secondary"
|
||||||
|
OnClick="@((e) => DenyFollowUp("Reject"))"
|
||||||
|
Disabled="@followUpDenyInProcess">
|
||||||
|
@if (followUpDenyInProcess) {
|
||||||
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
||||||
|
<MudText>Processing</MudText>
|
||||||
|
} else {
|
||||||
|
<MudText>Reject</MudText>
|
||||||
|
}
|
||||||
|
</MudButton>
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
<MudButton Variant="Variant.Filled"
|
||||||
|
Color="Color.Secondary"
|
||||||
|
OnClick="@((e) => DenyFollowUp("Recall"))"
|
||||||
|
Disabled="@followUpDenyInProcess">
|
||||||
|
@if (followUpDenyInProcess) {
|
||||||
|
<MudProgressCircular Class="m-1" Size="Size.Small" Indeterminate="true" />
|
||||||
|
<MudText>Processing</MudText>
|
||||||
|
} else {
|
||||||
|
<MudText>Recall</MudText>
|
||||||
|
}
|
||||||
|
</MudButton>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</MudStack>
|
||||||
|
</ToolBarContent>
|
||||||
|
<HeaderContent>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortBy="new Func<PCRBAttachment, object>(x=>x.FileName)">
|
||||||
|
File Name
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortBy="new Func<PCRBAttachment, object>(x=>x.UploadedBy is null ? string.Empty : x.UploadedBy.LastName)">
|
||||||
|
Uploaded By
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
<MudTh>
|
||||||
|
<MudTableSortLabel SortBy="new Func<PCRBAttachment, object>(x=>x.UploadDateTime)">
|
||||||
|
Uploaded Date
|
||||||
|
</MudTableSortLabel>
|
||||||
|
</MudTh>
|
||||||
|
</HeaderContent>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd DataLabel="File Name">
|
||||||
|
<a href="@(@$"{config["FabApprovalApiBaseUrl"]}/pcrb/attachmentFile?path={context.Path}&fileName={context.FileName}")"
|
||||||
|
download="@(context.FileName)"
|
||||||
|
target="_top">
|
||||||
|
@context.FileName
|
||||||
|
</a>
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="Uploaded By">@(context.UploadedBy is null ? string.Empty : context.UploadedBy.GetFullName())</MudTd>
|
||||||
|
<MudTd DataLabel="Uploaded Date">@context.UploadDateTime.ToString("yyyy-MM-dd HH:mm")</MudTd>
|
||||||
|
@if (!pcrb.FollowUps.First().IsComplete && !pcrb.FollowUps.First().IsPendingApproval)
|
||||||
|
{
|
||||||
|
<MudTd Style="text-align:center;">
|
||||||
|
<MudButton Color="Color.Secondary"
|
||||||
|
Variant="Variant.Filled"
|
||||||
|
Disabled="@deleteAttachmentInProcess"
|
||||||
|
OnClick="@((e) => DeleteAttachment(context))">
|
||||||
|
@if (deleteAttachmentInProcess)
|
||||||
|
{
|
||||||
|
<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 d-flex flex-column flex-wrap">
|
||||||
|
<MudText Typo="Typo.h5" Align="Align.Center">Follow Up Date</MudText>
|
||||||
|
<MudDatePicker Label="Follow Up Date"
|
||||||
|
Date="pcrb.FollowUps.First().FollowUpDate"
|
||||||
|
MinDate="@(pcrb.ClosedDate)"
|
||||||
|
Color="@Color.Tertiary"
|
||||||
|
Disabled="@(!userIsQA ||
|
||||||
|
pcrb.FollowUps.Count() == 0 ||
|
||||||
|
pcrb.FollowUps.First().IsComplete ||
|
||||||
|
pcrb.FollowUps.First().IsPendingApproval)"
|
||||||
|
Rounded="true"
|
||||||
|
Error="false"
|
||||||
|
Elevation="6"
|
||||||
|
DateChanged="UpdateFollowUpDate"
|
||||||
|
Variant="Variant.Outlined" />
|
||||||
|
</MudPaper>
|
||||||
|
@if (followUpComments.Count() > 0) {
|
||||||
|
<MudPaper Outlined="true" Class="p-1" Elevation="15">
|
||||||
|
<MudText Typo="Typo.h5" Align="Align.Center">Revision Comments</MudText>
|
||||||
|
<MudTable Items="@followUpComments"
|
||||||
|
Class="m-2"
|
||||||
|
Striped="true"
|
||||||
|
Hover="true">
|
||||||
|
<HeaderContent>
|
||||||
|
<MudTh>Date</MudTh>
|
||||||
|
<MudTh>User</MudTh>
|
||||||
|
<MudTh>Comment</MudTh>
|
||||||
|
</HeaderContent>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd DataLabel="Date">@context.CommentDate.ToString("MM/dd/yyyy hh:mm")</MudTd>
|
||||||
|
<MudTd DataLabel="User">@(context.User?.GetFullName() ?? string.Empty)</MudTd>
|
||||||
|
<MudTd DataLabel="Comment">@context.Comment</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
</MudTable>
|
||||||
|
</MudPaper>
|
||||||
|
}
|
||||||
|
</MudPaper>
|
||||||
|
</ChildContent>
|
||||||
|
</MudExpansionPanel>
|
||||||
|
}
|
||||||
</MudExpansionPanels>
|
</MudExpansionPanels>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,36 +34,39 @@ public partial class PCRBSingle {
|
|||||||
private IEnumerable<PCRBAttachment> attachments = new List<PCRBAttachment>();
|
private IEnumerable<PCRBAttachment> attachments = new List<PCRBAttachment>();
|
||||||
private IEnumerable<PCRBActionItem> actionItems = new List<PCRBActionItem>();
|
private IEnumerable<PCRBActionItem> actionItems = new List<PCRBActionItem>();
|
||||||
private IEnumerable<PCR3Document> pcr3Documents = new List<PCR3Document>();
|
private IEnumerable<PCR3Document> pcr3Documents = new List<PCR3Document>();
|
||||||
|
private IEnumerable<PCRBFollowUpComment> followUpComments = new List<PCRBFollowUpComment>();
|
||||||
|
|
||||||
|
private DateTime? followUpDate;
|
||||||
|
|
||||||
private IEnumerable<int> qualityApproverUserIds = new List<int>();
|
private IEnumerable<int> qualityApproverUserIds = new List<int>();
|
||||||
|
|
||||||
private IEnumerable<User> allActiveUsers = new List<User>();
|
private IEnumerable<User> allActiveUsers = new List<User>();
|
||||||
private User selectedOwner = null;
|
private User selectedOwner = null;
|
||||||
|
|
||||||
|
private bool userIsQA = false;
|
||||||
|
|
||||||
private bool processing = false;
|
private bool processing = false;
|
||||||
private bool saveInProcess = false;
|
private bool saveInProcess = false;
|
||||||
private bool deleteInProcess = false;
|
private bool deleteInProcess = false;
|
||||||
private bool submitInProcess = false;
|
private bool submitInProcess = false;
|
||||||
private bool approvalInProcess = false;
|
|
||||||
private bool denialInProcess = false;
|
|
||||||
private bool recallInProcess = false;
|
|
||||||
private bool attachmentUploadInProcess = false;
|
private bool attachmentUploadInProcess = false;
|
||||||
private bool updateAttachmentInProcess = false;
|
|
||||||
private bool deleteAttachmentInProcess = false;
|
private bool deleteAttachmentInProcess = false;
|
||||||
private bool addActionItemInProcess = false;
|
private bool followUpSubmitInProcess = false;
|
||||||
|
private bool followUpApproveInProcess = false;
|
||||||
private string attachmentSearchString = "";
|
private bool followUpDenyInProcess = false;
|
||||||
|
|
||||||
private string actionItemSearchString = "";
|
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync() {
|
protected override async Task OnParametersSetAsync() {
|
||||||
processing = true;
|
processing = true;
|
||||||
try {
|
try {
|
||||||
|
cache.Set("redirectUrl", $"pcrb/{planNumber}");
|
||||||
|
|
||||||
allActiveUsers = await userService.GetAllActiveUsers();
|
allActiveUsers = await userService.GetAllActiveUsers();
|
||||||
|
|
||||||
if (qualityApproverUserIds.Count() == 0)
|
if (qualityApproverUserIds.Count() == 0)
|
||||||
qualityApproverUserIds = await GetQualityApproverUserIds();
|
qualityApproverUserIds = await GetQualityApproverUserIds();
|
||||||
|
|
||||||
|
userIsQA = qualityApproverUserIds.Contains(authStateProvider.CurrentUser?.UserID ?? -1);
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(planNumber) && Int32.TryParse(planNumber, out planNumberInt)) {
|
if (!string.IsNullOrWhiteSpace(planNumber) && Int32.TryParse(planNumber, out planNumberInt)) {
|
||||||
pcrb = await pcrbService.GetPCRBByPlanNumber(planNumberInt, false);
|
pcrb = await pcrbService.GetPCRBByPlanNumber(planNumberInt, false);
|
||||||
approvals = await approvalService.GetApprovalsForIssueId(planNumberInt, false);
|
approvals = await approvalService.GetApprovalsForIssueId(planNumberInt, false);
|
||||||
@ -71,6 +74,10 @@ public partial class PCRBSingle {
|
|||||||
attachments = await pcrbService.GetAttachmentsByPlanNumber(planNumberInt, false);
|
attachments = await pcrbService.GetAttachmentsByPlanNumber(planNumberInt, false);
|
||||||
actionItems = await pcrbService.GetActionItemsForPlanNumber(planNumberInt, false);
|
actionItems = await pcrbService.GetActionItemsForPlanNumber(planNumberInt, false);
|
||||||
pcr3Documents = await pcrbService.GetPCR3DocumentsForPlanNumber(planNumberInt, false);
|
pcr3Documents = await pcrbService.GetPCR3DocumentsForPlanNumber(planNumberInt, false);
|
||||||
|
followUpComments = await pcrbService.GetFollowUpCommentsByPlanNumber(planNumberInt, false);
|
||||||
|
|
||||||
|
if (followUpDate is null)
|
||||||
|
followUpDate = pcrb.FollowUps.Count() > 0 ? pcrb.FollowUps.First().FollowUpDate : DateTimeUtilities.MAX_DT;
|
||||||
|
|
||||||
List<Task> createPCR3DocumentTasks = new();
|
List<Task> createPCR3DocumentTasks = new();
|
||||||
if (pcr3Documents.Count() <= 0) {
|
if (pcr3Documents.Count() <= 0) {
|
||||||
@ -117,9 +124,9 @@ public partial class PCRBSingle {
|
|||||||
|
|
||||||
if (pcrb.OwnerID > 0) selectedOwner = await userService.GetUserByUserId(pcrb.OwnerID);
|
if (pcrb.OwnerID > 0) selectedOwner = await userService.GetUserByUserId(pcrb.OwnerID);
|
||||||
|
|
||||||
if (pcrb.CurrentStep > 0 && pcrb.CurrentStep < 4) {
|
if (pcrb.CurrentStep > (int)PCRB.StagesEnum.Draft && pcrb.CurrentStep < (int)PCRB.StagesEnum.Complete) {
|
||||||
bool stageHasAdvanced = false;
|
bool stageHasAdvanced = false;
|
||||||
for (int stage = pcrb.CurrentStep; stage < 4; stage++) {
|
for (int stage = pcrb.CurrentStep; stage < (int)PCRB.StagesEnum.Complete; stage++) {
|
||||||
int current_stage = stage;
|
int current_stage = stage;
|
||||||
if (pcrb.CurrentStep == current_stage) {
|
if (pcrb.CurrentStep == current_stage) {
|
||||||
IEnumerable<Approval> currentStageApprovals = approvals.Where(a => a.Step == current_stage);
|
IEnumerable<Approval> currentStageApprovals = approvals.Where(a => a.Step == current_stage);
|
||||||
@ -128,7 +135,7 @@ public partial class PCRBSingle {
|
|||||||
bool currentStageApproved = currentStageApprovedApprovalsCount >= 3 && currentStagePendingApprovalsCount == 0;
|
bool currentStageApproved = currentStageApprovedApprovalsCount >= 3 && currentStagePendingApprovalsCount == 0;
|
||||||
|
|
||||||
if (currentStageApproved) {
|
if (currentStageApproved) {
|
||||||
if (pcrb.CurrentStep == 3) {
|
if (pcrb.CurrentStep == (int)PCRB.StagesEnum.PCR3) {
|
||||||
int openActionItemCount = actionItems.Where(a => a.ClosedByID == 0).Count();
|
int openActionItemCount = actionItems.Where(a => a.ClosedByID == 0).Count();
|
||||||
int openAffectedDocumentsCount = pcr3Documents.Where(d => d.CompletedByID == 0).Count();
|
int openAffectedDocumentsCount = pcr3Documents.Where(d => d.CompletedByID == 0).Count();
|
||||||
|
|
||||||
@ -145,7 +152,7 @@ public partial class PCRBSingle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (stageHasAdvanced) {
|
if (stageHasAdvanced) {
|
||||||
if (pcrb.CurrentStep == 4) {
|
if (pcrb.CurrentStep == (int)PCRB.StagesEnum.Complete) {
|
||||||
pcrb.ClosedDate = DateTime.Now;
|
pcrb.ClosedDate = DateTime.Now;
|
||||||
|
|
||||||
string message = $"PCRB# {pcrb.PlanNumber} - {pcrb.Title} is complete";
|
string message = $"PCRB# {pcrb.PlanNumber} - {pcrb.Title} is complete";
|
||||||
@ -165,6 +172,34 @@ public partial class PCRBSingle {
|
|||||||
await OnParametersSetAsync();
|
await OnParametersSetAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pcrb.CurrentStep == (int)PCRB.StagesEnum.Complete && pcrb.FollowUps.Count() == 0) {
|
||||||
|
PCRBFollowUp followUp = new() {
|
||||||
|
PlanNumber = pcrb.PlanNumber,
|
||||||
|
Step = (int)PCRB.StagesEnum.FollowUp,
|
||||||
|
FollowUpDate = pcrb.ClosedDate.AddMonths(6)
|
||||||
|
};
|
||||||
|
|
||||||
|
await pcrbService.CreateFollowUp(followUp);
|
||||||
|
|
||||||
|
pcrb = await pcrbService.GetPCRBByPlanNumber(pcrb.PlanNumber, true);
|
||||||
|
|
||||||
|
if (pcrb.FollowUps.Count() == 0)
|
||||||
|
throw new Exception("unable to create follow up");
|
||||||
|
|
||||||
|
StateHasChanged();
|
||||||
|
await OnParametersSetAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pcrb.CurrentStep == (int)PCRB.StagesEnum.Complete && pcrb.FollowUps.Count() > 0 &&
|
||||||
|
DateTime.Now >= pcrb.FollowUps.First().FollowUpDate.AddDays(-15)) {
|
||||||
|
pcrb.CurrentStep = (int)PCRB.StagesEnum.FollowUp;
|
||||||
|
await pcrbService.UpdatePCRB(pcrb);
|
||||||
|
pcrb = await pcrbService.GetPCRBByPlanNumber(pcrb.PlanNumber, true);
|
||||||
|
|
||||||
|
StateHasChanged();
|
||||||
|
await OnParametersSetAsync();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
int ownerID = 0;
|
int ownerID = 0;
|
||||||
string ownerName = string.Empty;
|
string ownerName = string.Empty;
|
||||||
@ -177,7 +212,7 @@ public partial class PCRBSingle {
|
|||||||
pcrb = new() {
|
pcrb = new() {
|
||||||
OwnerID = ownerID,
|
OwnerID = ownerID,
|
||||||
OwnerName = ownerName,
|
OwnerName = ownerName,
|
||||||
CurrentStep = 0
|
CurrentStep = (int)PCRB.StagesEnum.Draft
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,7 +250,7 @@ public partial class PCRBSingle {
|
|||||||
private bool PCRBReadyToSubmit(int step) {
|
private bool PCRBReadyToSubmit(int step) {
|
||||||
bool readyToSubmit = GetIncompleteFields().Count() <= 0;
|
bool readyToSubmit = GetIncompleteFields().Count() <= 0;
|
||||||
|
|
||||||
readyToSubmit = readyToSubmit && pcrb.CurrentStep > 0;
|
readyToSubmit = readyToSubmit && pcrb.CurrentStep > (int)PCRB.StagesEnum.Draft;
|
||||||
|
|
||||||
readyToSubmit = readyToSubmit && attachments.Where(a => a.Step == step).Count() > 0;
|
readyToSubmit = readyToSubmit && attachments.Where(a => a.Step == step).Count() > 0;
|
||||||
|
|
||||||
@ -241,7 +276,7 @@ public partial class PCRBSingle {
|
|||||||
pcrb.OwnerID = selectedOwner.UserID;
|
pcrb.OwnerID = selectedOwner.UserID;
|
||||||
pcrb.OwnerName = selectedOwner.GetFullName();
|
pcrb.OwnerName = selectedOwner.GetFullName();
|
||||||
|
|
||||||
if (pcrb.CurrentStep == 0 && GetIncompleteFields().Count() <= 0)
|
if (pcrb.CurrentStep == (int)PCRB.StagesEnum.Draft && GetIncompleteFields().Count() <= 0)
|
||||||
pcrb.CurrentStep++;
|
pcrb.CurrentStep++;
|
||||||
|
|
||||||
if (initialPlanNumber <= 0) {
|
if (initialPlanNumber <= 0) {
|
||||||
@ -300,34 +335,54 @@ public partial class PCRBSingle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task<IEnumerable<int>> GetQualityApproverUserIds() {
|
private async Task<IEnumerable<int>> GetQualityApproverUserIds() {
|
||||||
List<int> qualityApproverUserIds = new();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int roleId = await approvalService.GetRoleIdForRoleName("Module Manager");
|
HashSet<int>? qualityApproverUserIds = cache.Get<HashSet<int>>("qualityApproverUserIds");
|
||||||
|
|
||||||
if (roleId <= 0) throw new Exception($"could not find Module Manager role ID");
|
if (qualityApproverUserIds is null || qualityApproverUserIds.Count() == 0) {
|
||||||
|
qualityApproverUserIds = new();
|
||||||
|
|
||||||
IEnumerable<SubRole> subRoles = await approvalService.GetSubRolesForSubRoleName("MMSubRole", roleId);
|
int roleId = await approvalService.GetRoleIdForRoleName("Module Manager");
|
||||||
|
|
||||||
foreach (SubRole subRole in subRoles) {
|
if (roleId <= 0) throw new Exception($"could not find Module Manager role ID");
|
||||||
if (subRole.SubRoleCategoryItem.Equals("Quality", StringComparison.InvariantCultureIgnoreCase)) {
|
|
||||||
|
IEnumerable<SubRole> subRoles = await approvalService.GetSubRolesForSubRoleName("MMSubRole", roleId);
|
||||||
|
|
||||||
|
foreach (SubRole subRole in subRoles) {
|
||||||
|
if (subRole.SubRoleCategoryItem.Equals("Quality", StringComparison.InvariantCultureIgnoreCase)) {
|
||||||
|
IEnumerable<User> subRoleMembers = await approvalService.GetApprovalGroupMembers(subRole.SubRoleID);
|
||||||
|
foreach (User user in subRoleMembers) qualityApproverUserIds.Add(user.UserID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string roleName = "QA_PRE_APPROVAL";
|
||||||
|
string subRoleName = "QA_PRE_APPROVAL";
|
||||||
|
|
||||||
|
roleId = await approvalService.GetRoleIdForRoleName(roleName);
|
||||||
|
|
||||||
|
if (roleId <= 0) throw new Exception($"could not find {roleName} role ID");
|
||||||
|
|
||||||
|
subRoles = await approvalService.GetSubRolesForSubRoleName(subRoleName, roleId);
|
||||||
|
|
||||||
|
foreach (SubRole subRole in subRoles) {
|
||||||
IEnumerable<User> subRoleMembers = await approvalService.GetApprovalGroupMembers(subRole.SubRoleID);
|
IEnumerable<User> subRoleMembers = await approvalService.GetApprovalGroupMembers(subRole.SubRoleID);
|
||||||
foreach (User user in subRoleMembers) qualityApproverUserIds.Add(user.UserID);
|
foreach (User user in subRoleMembers) qualityApproverUserIds.Add(user.UserID);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
string roleName = "QA_PRE_APPROVAL";
|
roleName = "QA_FINAL_APPROVAL";
|
||||||
string subRoleName = "QA_PRE_APPROVAL";
|
subRoleName = "QA_FINAL_APPROVAL";
|
||||||
|
|
||||||
roleId = await approvalService.GetRoleIdForRoleName(roleName);
|
roleId = await approvalService.GetRoleIdForRoleName(roleName);
|
||||||
|
|
||||||
if (roleId <= 0) throw new Exception($"could not find {roleName} role ID");
|
if (roleId <= 0) throw new Exception($"could not find {roleName} role ID");
|
||||||
|
|
||||||
subRoles = await approvalService.GetSubRolesForSubRoleName(subRoleName, roleId);
|
subRoles = await approvalService.GetSubRolesForSubRoleName(subRoleName, roleId);
|
||||||
|
|
||||||
foreach (SubRole subRole in subRoles) {
|
foreach (SubRole subRole in subRoles) {
|
||||||
IEnumerable<User> subRoleMembers = await approvalService.GetApprovalGroupMembers(subRole.SubRoleID);
|
IEnumerable<User> subRoleMembers = await approvalService.GetApprovalGroupMembers(subRole.SubRoleID);
|
||||||
foreach (User user in subRoleMembers) qualityApproverUserIds.Add(user.UserID);
|
foreach (User user in subRoleMembers) qualityApproverUserIds.Add(user.UserID);
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.Set("qualityApproverUserIds", qualityApproverUserIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
return qualityApproverUserIds;
|
return qualityApproverUserIds;
|
||||||
@ -445,9 +500,7 @@ public partial class PCRBSingle {
|
|||||||
Approval? latestQaPreApproval = currentStageApprovals
|
Approval? latestQaPreApproval = currentStageApprovals
|
||||||
.Where(a => a.SubRoleCategoryItem.Equals("QA Pre Approver"))
|
.Where(a => a.SubRoleCategoryItem.Equals("QA Pre Approver"))
|
||||||
.OrderByDescending(a => a.AssignedDate)
|
.OrderByDescending(a => a.AssignedDate)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault() ?? throw new Exception("QA pre approval not found");
|
||||||
|
|
||||||
if (latestQaPreApproval is null) throw new Exception("QA pre approval not found");
|
|
||||||
|
|
||||||
bool qaPreApprovalDenied = latestQaPreApproval.ItemStatus == -1;
|
bool qaPreApprovalDenied = latestQaPreApproval.ItemStatus == -1;
|
||||||
if (qaPreApprovalDenied && currentStageUnsubmittedApprovalCount >= 3) {
|
if (qaPreApprovalDenied && currentStageUnsubmittedApprovalCount >= 3) {
|
||||||
@ -493,9 +546,8 @@ public partial class PCRBSingle {
|
|||||||
await Task.WhenAll(createCopiedApprovalsTasks);
|
await Task.WhenAll(createCopiedApprovalsTasks);
|
||||||
} else {
|
} else {
|
||||||
Approval? unassignedQaPreApproval = currentStageApprovals.Where(a => a.SubRoleCategoryItem.Equals("QA Pre Approver") &&
|
Approval? unassignedQaPreApproval = currentStageApprovals.Where(a => a.SubRoleCategoryItem.Equals("QA Pre Approver") &&
|
||||||
a.AssignedDate <= DateTimeUtilities.MIN_DT).FirstOrDefault();
|
a.AssignedDate <= DateTimeUtilities.MIN_DT).FirstOrDefault() ??
|
||||||
|
throw new Exception("unassigned QA pre approval not found");
|
||||||
if (unassignedQaPreApproval is null) throw new Exception("unassigned QA pre approval not found");
|
|
||||||
|
|
||||||
unassignedQaPreApproval.AssignedDate = DateTime.Now;
|
unassignedQaPreApproval.AssignedDate = DateTime.Now;
|
||||||
await approvalService.UpdateApproval(unassignedQaPreApproval);
|
await approvalService.UpdateApproval(unassignedQaPreApproval);
|
||||||
@ -505,7 +557,7 @@ public partial class PCRBSingle {
|
|||||||
|
|
||||||
await pcrbService.NotifyNewApprovals(pcrb);
|
await pcrbService.NotifyNewApprovals(pcrb);
|
||||||
|
|
||||||
if (pcrb.CurrentStep == 1) {
|
if (pcrb.CurrentStep == (int)PCRB.StagesEnum.PCR1) {
|
||||||
pcrb.InsertTimeStamp = DateTime.Now;
|
pcrb.InsertTimeStamp = DateTime.Now;
|
||||||
await pcrbService.UpdatePCRB(pcrb);
|
await pcrbService.UpdatePCRB(pcrb);
|
||||||
|
|
||||||
@ -525,23 +577,6 @@ public partial class PCRBSingle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SetUserForApproval(Approval approval, User user) {
|
|
||||||
if (approval is null) throw new ArgumentNullException("approval cannot be null");
|
|
||||||
if (user is null) throw new ArgumentNullException("user cannot be null");
|
|
||||||
|
|
||||||
if (approval.CompletedDate < DateTimeUtilities.MAX_DT || approval.ItemStatus != 0)
|
|
||||||
throw new ArgumentException("cannot reassign a complete approval");
|
|
||||||
|
|
||||||
approval.UserID = user.UserID;
|
|
||||||
approval.User = user;
|
|
||||||
approval.NotifyDate = DateTimeUtilities.MIN_DT;
|
|
||||||
|
|
||||||
await approvalService.UpdateApproval(approval);
|
|
||||||
await approvalService.GetApprovalsForIssueId(approval.IssueID, true);
|
|
||||||
|
|
||||||
await pcrbService.NotifyNewApprovals(pcrb);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ApprovePCR(int step) {
|
private async Task ApprovePCR(int step) {
|
||||||
if (!processing) {
|
if (!processing) {
|
||||||
try {
|
try {
|
||||||
@ -1136,4 +1171,328 @@ public partial class PCRBSingle {
|
|||||||
if (itemStatus > 0) return "Approved";
|
if (itemStatus > 0) return "Approved";
|
||||||
return "Pending";
|
return "Pending";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task UpdateFollowUpDate(DateTime? newFollowUpDate) {
|
||||||
|
if (followUpDate is not null || followUpDate <= DateTimeUtilities.MAX_DT) {
|
||||||
|
try {
|
||||||
|
if (newFollowUpDate is null)
|
||||||
|
throw new Exception("follow up date cannot be null");
|
||||||
|
|
||||||
|
if (authStateProvider.CurrentUser is null) {
|
||||||
|
snackbar.Add("You must log in to change the follow up date", Severity.Error);
|
||||||
|
await authStateProvider.Logout();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime oldFollowUpDate = pcrb.FollowUps.First().FollowUpDate;
|
||||||
|
|
||||||
|
followUpDate = newFollowUpDate;
|
||||||
|
pcrb.FollowUps.First().FollowUpDate = (DateTime)newFollowUpDate;
|
||||||
|
await pcrbService.UpdateFollowUp(pcrb.FollowUps.First());
|
||||||
|
|
||||||
|
pcrb = await pcrbService.GetPCRBByPlanNumber(pcrb.PlanNumber, true);
|
||||||
|
|
||||||
|
string comments = "";
|
||||||
|
|
||||||
|
DialogParameters<Comments> parameters = new DialogParameters<Comments> { { x => x.comments, comments } };
|
||||||
|
var dialog = await dialogService.ShowAsync<Comments>($"Follow Up Date Change Comment", parameters);
|
||||||
|
|
||||||
|
DialogResult? result = await dialog.Result;
|
||||||
|
|
||||||
|
if (result is null || result.Canceled || result.Data is null || string.IsNullOrWhiteSpace(result.Data?.ToString())) {
|
||||||
|
followUpDate = oldFollowUpDate;
|
||||||
|
pcrb.FollowUps.First().FollowUpDate = oldFollowUpDate;
|
||||||
|
await pcrbService.UpdateFollowUp(pcrb.FollowUps.First());
|
||||||
|
|
||||||
|
pcrb = await pcrbService.GetPCRBByPlanNumber(pcrb.PlanNumber, true);
|
||||||
|
|
||||||
|
throw new Exception("you must provide a comment");
|
||||||
|
}
|
||||||
|
|
||||||
|
comments = result.Data?.ToString() ?? string.Empty;
|
||||||
|
|
||||||
|
comments = comments.Trim();
|
||||||
|
|
||||||
|
StringBuilder commentBuilder = new();
|
||||||
|
|
||||||
|
commentBuilder.Append($"Changing follow up date from {oldFollowUpDate.ToString("MM/dd/yyyy")} ");
|
||||||
|
commentBuilder.Append($"to {pcrb.FollowUps.First().FollowUpDate.ToString("MM/dd/yyyy")}. Comments: {comments}");
|
||||||
|
|
||||||
|
PCRBFollowUpComment comment = new() {
|
||||||
|
PlanNumber = pcrb.FollowUps.First().PlanNumber,
|
||||||
|
FollowUpID = pcrb.FollowUps.First().ID,
|
||||||
|
Comment = commentBuilder.ToString(),
|
||||||
|
UserID = authStateProvider.CurrentUser.UserID
|
||||||
|
};
|
||||||
|
|
||||||
|
await pcrbService.CreateFollowUpComment(comment);
|
||||||
|
|
||||||
|
DateTime fifteenDaysFromNow = DateTime.Now.AddDays(15);
|
||||||
|
|
||||||
|
if (pcrb.FollowUps.First().FollowUpDate > fifteenDaysFromNow) {
|
||||||
|
IEnumerable<Approval> step5Approvals = approvals.Where(a => a.Step == 5 && a.ItemStatus == 0);
|
||||||
|
foreach (Approval approval in step5Approvals) {
|
||||||
|
await approvalService.DeleteApproval(approval.ApprovalID);
|
||||||
|
await approvalService.GetApprovalsForUserId(approval.UserID, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
approvals = await approvalService.GetApprovalsForIssueId(pcrb.PlanNumber, true);
|
||||||
|
} else if (approvals.Where(a => a.Step == 5 && a.ItemStatus == 0).Count() == 0) {
|
||||||
|
Approval newApproval = new Approval {
|
||||||
|
IssueID = pcrb.PlanNumber,
|
||||||
|
RoleName = "PCRB Owner Follow Up",
|
||||||
|
SubRole = "PCRBOwnerFollowUp",
|
||||||
|
SubRoleCategoryItem = "PCRB Owner Follow Up",
|
||||||
|
UserID = pcrb.OwnerID,
|
||||||
|
SubRoleID = 999,
|
||||||
|
AssignedDate = DateTime.Now,
|
||||||
|
TaskID = pcrb.FollowUps.First().ID,
|
||||||
|
Step = 5,
|
||||||
|
NotifyDate = DateTime.Now
|
||||||
|
};
|
||||||
|
|
||||||
|
await approvalService.CreateApproval(newApproval);
|
||||||
|
}
|
||||||
|
|
||||||
|
commentBuilder.Clear();
|
||||||
|
commentBuilder.Append($"Effectiveness review date for PCRB# {pcrb.PlanNumber} - {pcrb.Title} has been changed to ");
|
||||||
|
commentBuilder.Append($"{pcrb.FollowUps.First().FollowUpDate.ToString("MM/dd/yyyy")}. ");
|
||||||
|
|
||||||
|
PCRBNotification notification = new() {
|
||||||
|
Message = commentBuilder.ToString(),
|
||||||
|
Subject = $"[PCRB Effectiveness Review Date Change] {pcrb.PlanNumber} - {pcrb.Title}",
|
||||||
|
PCRB = pcrb,
|
||||||
|
NotifyQaPreApprover = true
|
||||||
|
};
|
||||||
|
|
||||||
|
await pcrbService.NotifyOriginator(notification);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
snackbar.Add($"Unable to update follow up date, because {ex.Message}", Severity.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
StateHasChanged();
|
||||||
|
await OnParametersSetAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SubmitFollowUpForApproval() {
|
||||||
|
if (!followUpSubmitInProcess) {
|
||||||
|
try {
|
||||||
|
followUpSubmitInProcess = true;
|
||||||
|
|
||||||
|
if (pcrb.FollowUps.Count() > 0) {
|
||||||
|
PCRBFollowUp followUp = pcrb.FollowUps.First();
|
||||||
|
followUp.IsPendingApproval = true;
|
||||||
|
await pcrbService.UpdateFollowUp(followUp);
|
||||||
|
|
||||||
|
List<SubRole> allSubRoles = new();
|
||||||
|
|
||||||
|
int roleId = await approvalService.GetRoleIdForRoleName("Module Manager");
|
||||||
|
|
||||||
|
if (roleId <= 0) throw new Exception($"could not find Module Manager role ID");
|
||||||
|
|
||||||
|
List<SubRole> qualityMMSubRoles = (await approvalService.GetSubRolesForSubRoleName("MMSubRole", roleId)).ToList();
|
||||||
|
|
||||||
|
foreach (SubRole subRole in qualityMMSubRoles) {
|
||||||
|
if (subRole.SubRoleCategoryItem.Equals("Quality"))
|
||||||
|
allSubRoles.Add(subRole);
|
||||||
|
}
|
||||||
|
|
||||||
|
roleId = await approvalService.GetRoleIdForRoleName("QA_FINAL_APPROVAL");
|
||||||
|
|
||||||
|
if (roleId <= 0) throw new Exception($"could not find QA Final Approval role ID");
|
||||||
|
|
||||||
|
IEnumerable<SubRole> qaFinalApprovalSubRoles =
|
||||||
|
(await approvalService.GetSubRolesForSubRoleName("QA_FINAL_APPROVAL", roleId)).ToList();
|
||||||
|
|
||||||
|
foreach (SubRole subRole in qaFinalApprovalSubRoles)
|
||||||
|
allSubRoles.Add(subRole);
|
||||||
|
|
||||||
|
foreach (SubRole subRole in allSubRoles) {
|
||||||
|
IEnumerable<User> subRoleMembers = await approvalService.GetApprovalGroupMembers(subRole.SubRoleID);
|
||||||
|
|
||||||
|
foreach (User member in subRoleMembers) {
|
||||||
|
Approval approval = new() {
|
||||||
|
IssueID = pcrb.PlanNumber,
|
||||||
|
RoleName = subRole.SubRoleCategoryItem,
|
||||||
|
SubRole = subRole.SubRoleName,
|
||||||
|
UserID = member.UserID,
|
||||||
|
SubRoleID = subRole.SubRoleID,
|
||||||
|
AssignedDate = DateTime.Now,
|
||||||
|
Step = followUp.Step,
|
||||||
|
TaskID = followUp.ID
|
||||||
|
};
|
||||||
|
|
||||||
|
await approvalService.CreateApproval(approval);
|
||||||
|
|
||||||
|
approvals = await approvalService.GetApprovalsForIssueId(pcrb.PlanNumber, true);
|
||||||
|
|
||||||
|
approval = approvals.Where(a => a.TaskID == followUp.ID &&
|
||||||
|
a.RoleName.Equals(subRole.SubRoleCategoryItem) &&
|
||||||
|
a.UserID == member.UserID &&
|
||||||
|
a.Step == followUp.Step).First();
|
||||||
|
|
||||||
|
PCRBNotification notification = new() {
|
||||||
|
PCRB = pcrb,
|
||||||
|
Subject = $"[PCRB Follow Up] {pcrb.PlanNumber} - {pcrb.Title}",
|
||||||
|
Message = $"Follow up for PCRB# {pcrb.PlanNumber} - {pcrb.Title} has been submitted for closure.",
|
||||||
|
Approval = approval
|
||||||
|
};
|
||||||
|
|
||||||
|
await pcrbService.NotifyApprover(notification);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string comments = "Submitted for closure";
|
||||||
|
|
||||||
|
PCRBFollowUpComment comment = new() {
|
||||||
|
PlanNumber = followUp.PlanNumber,
|
||||||
|
FollowUpID = followUp.ID,
|
||||||
|
Comment = comments,
|
||||||
|
UserID = authStateProvider.CurrentUser.UserID
|
||||||
|
};
|
||||||
|
|
||||||
|
await pcrbService.CreateFollowUpComment(comment);
|
||||||
|
|
||||||
|
snackbar.Add("Follow up submitted for closure", Severity.Success);
|
||||||
|
} else {
|
||||||
|
throw new Exception("no follow ups available to mark as pending closure");
|
||||||
|
}
|
||||||
|
|
||||||
|
followUpSubmitInProcess = false;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
followUpSubmitInProcess = false;
|
||||||
|
snackbar.Add($"Unable to submit follow up for closure, because {ex.Message}", Severity.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
StateHasChanged();
|
||||||
|
await OnParametersSetAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ApproveFollowUp() {
|
||||||
|
if (!followUpApproveInProcess) {
|
||||||
|
try {
|
||||||
|
followUpApproveInProcess = true;
|
||||||
|
|
||||||
|
IEnumerable<Approval> step5Approvals = approvals.Where(a => a.Step == 5 && a.ItemStatus == 0);
|
||||||
|
foreach (Approval approval in step5Approvals) {
|
||||||
|
approval.ItemStatus = 1;
|
||||||
|
approval.Comments = "Follow up complete";
|
||||||
|
approval.CompletedDate = DateTime.Now;
|
||||||
|
await approvalService.UpdateApproval(approval);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (PCRBFollowUp? followUp in pcrb.FollowUps.Where(f => !f.IsComplete)) {
|
||||||
|
followUp.IsComplete = true;
|
||||||
|
followUp.IsPendingApproval = false;
|
||||||
|
followUp.CompletedDate = DateTime.Now;
|
||||||
|
await pcrbService.UpdateFollowUp(followUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
pcrb.CurrentStep = (int)PCRB.StagesEnum.Closed;
|
||||||
|
await pcrbService.UpdatePCRB(pcrb);
|
||||||
|
|
||||||
|
string comments = "Follow up complete";
|
||||||
|
|
||||||
|
PCRBFollowUpComment comment = new() {
|
||||||
|
PlanNumber = pcrb.PlanNumber,
|
||||||
|
FollowUpID = pcrb.FollowUps.First().ID,
|
||||||
|
Comment = comments,
|
||||||
|
UserID = authStateProvider.CurrentUser.UserID
|
||||||
|
};
|
||||||
|
|
||||||
|
await pcrbService.CreateFollowUpComment(comment);
|
||||||
|
|
||||||
|
PCRBNotification notification = new() {
|
||||||
|
PCRB = pcrb,
|
||||||
|
Message = $"Follow up for PCRB# {pcrb.PlanNumber} - {pcrb.Title} has been closed."
|
||||||
|
};
|
||||||
|
|
||||||
|
await pcrbService.NotifyOriginator(notification);
|
||||||
|
|
||||||
|
followUpApproveInProcess = false;
|
||||||
|
|
||||||
|
snackbar.Add("Follow up successfully approved", Severity.Success);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
followUpApproveInProcess = false;
|
||||||
|
snackbar.Add($"Unable to approve follow up, because {ex.Message}", Severity.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
StateHasChanged();
|
||||||
|
await OnParametersSetAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DenyFollowUp(string action) {
|
||||||
|
if (!followUpDenyInProcess) {
|
||||||
|
try {
|
||||||
|
string pastAction = action.ToLower().Equals("recall") ? "recalled" : "rejected";
|
||||||
|
|
||||||
|
followUpDenyInProcess = true;
|
||||||
|
|
||||||
|
string comments = "";
|
||||||
|
|
||||||
|
DialogParameters<Comments> parameters = new DialogParameters<Comments> { { x => x.comments, comments } };
|
||||||
|
var dialog = await dialogService.ShowAsync<Comments>($"Follow Up {action} Comment", parameters);
|
||||||
|
|
||||||
|
DialogResult? result = await dialog.Result;
|
||||||
|
|
||||||
|
if (result is null || result.Canceled || result.Data is null || string.IsNullOrWhiteSpace(result.Data?.ToString())) {
|
||||||
|
throw new Exception("you must provide a comment");
|
||||||
|
}
|
||||||
|
|
||||||
|
comments = result.Data?.ToString() ?? string.Empty;
|
||||||
|
|
||||||
|
comments = comments.Trim();
|
||||||
|
|
||||||
|
IEnumerable<Approval> step5Approvals = approvals.Where(a => a.Step == 5 &&
|
||||||
|
a.ItemStatus == 0 &&
|
||||||
|
a.UserID != pcrb.OwnerID);
|
||||||
|
foreach (Approval approval in step5Approvals) {
|
||||||
|
approval.ItemStatus = -1;
|
||||||
|
approval.CompletedDate = DateTime.Now;
|
||||||
|
approval.Comments = comments is null ? string.Empty : comments;
|
||||||
|
await approvalService.UpdateApproval(approval);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var followUp in pcrb.FollowUps.Where(f => f.IsPendingApproval)) {
|
||||||
|
followUp.IsPendingApproval = false;
|
||||||
|
await pcrbService.UpdateFollowUp(followUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder messageBuilder = new();
|
||||||
|
messageBuilder.Append($"Follow up for PCRB# {pcrb.PlanNumber} - {pcrb.Title} has been {pastAction}. ");
|
||||||
|
messageBuilder.Append($"Please review the comments and make the necessary revisions. Comments: {comments}");
|
||||||
|
|
||||||
|
PCRBNotification notification = new() {
|
||||||
|
PCRB = pcrb,
|
||||||
|
Message = messageBuilder.ToString()
|
||||||
|
};
|
||||||
|
|
||||||
|
await pcrbService.NotifyOriginator(notification);
|
||||||
|
|
||||||
|
comments = $"Follow up {pastAction}. Comments: {comments}";
|
||||||
|
|
||||||
|
PCRBFollowUpComment comment = new() {
|
||||||
|
PlanNumber = pcrb.PlanNumber,
|
||||||
|
FollowUpID = pcrb.FollowUps.First().ID,
|
||||||
|
Comment = comments,
|
||||||
|
UserID = authStateProvider.CurrentUser.UserID
|
||||||
|
};
|
||||||
|
|
||||||
|
await pcrbService.CreateFollowUpComment(comment);
|
||||||
|
|
||||||
|
followUpDenyInProcess = false;
|
||||||
|
|
||||||
|
snackbar.Add($"Follow up successfully {pastAction}", Severity.Success);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
followUpDenyInProcess = false;
|
||||||
|
snackbar.Add($"Unable to {action.ToLower()} follow up, because {ex.Message}", Severity.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
StateHasChanged();
|
||||||
|
await OnParametersSetAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ public interface IApprovalService {
|
|||||||
Task<IEnumerable<User>> GetApprovalGroupMembers(int subRoleId);
|
Task<IEnumerable<User>> GetApprovalGroupMembers(int subRoleId);
|
||||||
Task CreateApproval(Approval approval);
|
Task CreateApproval(Approval approval);
|
||||||
Task UpdateApproval(Approval approval);
|
Task UpdateApproval(Approval approval);
|
||||||
|
Task DeleteApproval(int approvalID);
|
||||||
Task Approve(Approval approval);
|
Task Approve(Approval approval);
|
||||||
Task Deny(Approval approval);
|
Task Deny(Approval approval);
|
||||||
Task<IEnumerable<Approval>> GetApprovalsForIssueId(int issueId, bool bypassCache);
|
Task<IEnumerable<Approval>> GetApprovalsForIssueId(int issueId, bool bypassCache);
|
||||||
@ -156,6 +157,20 @@ public class ApprovalService : IApprovalService {
|
|||||||
await GetApprovalsForUserId(approval.UserID, true);
|
await GetApprovalsForUserId(approval.UserID, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task DeleteApproval(int approvalID) {
|
||||||
|
if (approvalID <= 0) throw new ArgumentException("Invalid approval ID");
|
||||||
|
|
||||||
|
HttpClient httpClient = _httpClientFactory.CreateClient("API");
|
||||||
|
|
||||||
|
HttpRequestMessage requestMessage = new(HttpMethod.Delete, $"approval?approvalID={approvalID}");
|
||||||
|
|
||||||
|
HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage);
|
||||||
|
|
||||||
|
if (!responseMessage.IsSuccessStatusCode) {
|
||||||
|
throw new Exception($"Unable to delete approval, because {responseMessage.ReasonPhrase}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task Approve(Approval approval) {
|
public async Task Approve(Approval approval) {
|
||||||
if (approval is null) throw new ArgumentNullException("approval cannot be null");
|
if (approval is null) throw new ArgumentNullException("approval cannot be null");
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using MesaFabApproval.Shared.Models;
|
using MesaFabApproval.Shared.Models;
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.AspNetCore.Components.Authorization;
|
using Microsoft.AspNetCore.Components.Authorization;
|
||||||
|
|
||||||
using MudBlazor;
|
using MudBlazor;
|
||||||
@ -12,18 +13,22 @@ public class MesaFabApprovalAuthStateProvider : AuthenticationStateProvider, IDi
|
|||||||
private readonly IAuthenticationService _authService;
|
private readonly IAuthenticationService _authService;
|
||||||
private readonly IUserService _userService;
|
private readonly IUserService _userService;
|
||||||
private readonly ISnackbar _snackbar;
|
private readonly ISnackbar _snackbar;
|
||||||
|
private readonly NavigationManager _navigationManager;
|
||||||
|
|
||||||
public User? CurrentUser { get; private set; }
|
public User? CurrentUser { get; private set; }
|
||||||
|
|
||||||
public MesaFabApprovalAuthStateProvider(IAuthenticationService authService,
|
public MesaFabApprovalAuthStateProvider(IAuthenticationService authService,
|
||||||
ISnackbar snackbar,
|
ISnackbar snackbar,
|
||||||
IUserService userService) {
|
IUserService userService,
|
||||||
|
NavigationManager navigationManager) {
|
||||||
_authService = authService ??
|
_authService = authService ??
|
||||||
throw new ArgumentNullException("IAuthenticationService not injected");
|
throw new ArgumentNullException("IAuthenticationService not injected");
|
||||||
_snackbar = snackbar ??
|
_snackbar = snackbar ??
|
||||||
throw new ArgumentNullException("ISnackbar not injected");
|
throw new ArgumentNullException("ISnackbar not injected");
|
||||||
_userService = userService ??
|
_userService = userService ??
|
||||||
throw new ArgumentNullException("IUserService not injected");
|
throw new ArgumentNullException("IUserService not injected");
|
||||||
|
_navigationManager = navigationManager ??
|
||||||
|
throw new ArgumentNullException("NavigationManager not injected");
|
||||||
AuthenticationStateChanged += OnAuthenticationStateChangedAsync;
|
AuthenticationStateChanged += OnAuthenticationStateChangedAsync;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ public interface IPCRBService {
|
|||||||
Task UpdatePCR3Document(PCR3Document document);
|
Task UpdatePCR3Document(PCR3Document document);
|
||||||
Task<IEnumerable<PCR3Document>> GetPCR3DocumentsForPlanNumber(int planNumber, bool bypassCache);
|
Task<IEnumerable<PCR3Document>> GetPCR3DocumentsForPlanNumber(int planNumber, bool bypassCache);
|
||||||
Task NotifyNewApprovals(PCRB pcrb);
|
Task NotifyNewApprovals(PCRB pcrb);
|
||||||
|
Task NotifyApprover(PCRBNotification notification);
|
||||||
Task NotifyApprovers(PCRBNotification notification);
|
Task NotifyApprovers(PCRBNotification notification);
|
||||||
Task NotifyOriginator(PCRBNotification notification);
|
Task NotifyOriginator(PCRBNotification notification);
|
||||||
Task NotifyResponsiblePerson(PCRBActionItemNotification notification);
|
Task NotifyResponsiblePerson(PCRBActionItemNotification notification);
|
||||||
@ -43,6 +44,10 @@ public interface IPCRBService {
|
|||||||
Task<IEnumerable<PCRBFollowUp>> GetFollowUpsByPlanNumber(int planNumber, bool bypassCache);
|
Task<IEnumerable<PCRBFollowUp>> GetFollowUpsByPlanNumber(int planNumber, bool bypassCache);
|
||||||
Task UpdateFollowUp(PCRBFollowUp followUp);
|
Task UpdateFollowUp(PCRBFollowUp followUp);
|
||||||
Task DeleteFollowUp(int id);
|
Task DeleteFollowUp(int id);
|
||||||
|
Task CreateFollowUpComment(PCRBFollowUpComment comment);
|
||||||
|
Task<IEnumerable<PCRBFollowUpComment>> GetFollowUpCommentsByPlanNumber(int planNumber, bool bypassCache);
|
||||||
|
Task UpdateFollowUpComment(PCRBFollowUpComment comment);
|
||||||
|
Task DeleteFollowUpComment(int id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PCRBService : IPCRBService {
|
public class PCRBService : IPCRBService {
|
||||||
@ -712,6 +717,26 @@ public class PCRBService : IPCRBService {
|
|||||||
throw new Exception($"Unable to notify new PCRB approvers, because {responseMessage.ReasonPhrase}");
|
throw new Exception($"Unable to notify new PCRB approvers, because {responseMessage.ReasonPhrase}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task NotifyApprover(PCRBNotification notification) {
|
||||||
|
if (notification is null) throw new ArgumentNullException("notification cannot be null");
|
||||||
|
if (notification.PCRB is null) throw new ArgumentNullException("PCRB cannot be null");
|
||||||
|
if (notification.Approval is null) throw new ArgumentNullException("approval 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, $"pcrb/notify/approver") {
|
||||||
|
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 PCRB approver, because {responseMessage.ReasonPhrase}");
|
||||||
|
}
|
||||||
|
|
||||||
public async Task NotifyApprovers(PCRBNotification notification) {
|
public async Task NotifyApprovers(PCRBNotification notification) {
|
||||||
if (notification is null) throw new ArgumentNullException("notification cannot be null");
|
if (notification is null) throw new ArgumentNullException("notification cannot be null");
|
||||||
if (notification.PCRB is null) throw new ArgumentNullException("PCRB cannot be null");
|
if (notification.PCRB is null) throw new ArgumentNullException("PCRB cannot be null");
|
||||||
@ -812,7 +837,7 @@ public class PCRBService : IPCRBService {
|
|||||||
new List<PCRBFollowUp>();
|
new List<PCRBFollowUp>();
|
||||||
|
|
||||||
if (followUps.Count() > 0)
|
if (followUps.Count() > 0)
|
||||||
_cache.Set($"pcrbFollowUps{planNumber}", followUps, DateTimeOffset.Now.AddMinutes(5));
|
_cache.Set($"pcrbFollowUps{planNumber}", followUps, DateTimeOffset.Now.AddHours(1));
|
||||||
} else {
|
} else {
|
||||||
throw new Exception(responseMessage.ReasonPhrase);
|
throw new Exception(responseMessage.ReasonPhrase);
|
||||||
}
|
}
|
||||||
@ -836,6 +861,8 @@ public class PCRBService : IPCRBService {
|
|||||||
|
|
||||||
if (!responseMessage.IsSuccessStatusCode)
|
if (!responseMessage.IsSuccessStatusCode)
|
||||||
throw new Exception(responseMessage.ReasonPhrase);
|
throw new Exception(responseMessage.ReasonPhrase);
|
||||||
|
|
||||||
|
await GetFollowUpsByPlanNumber(followUp.PlanNumber, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteFollowUp(int id) {
|
public async Task DeleteFollowUp(int id) {
|
||||||
@ -849,4 +876,93 @@ public class PCRBService : IPCRBService {
|
|||||||
|
|
||||||
if (!responseMessage.IsSuccessStatusCode) throw new Exception(responseMessage.ReasonPhrase);
|
if (!responseMessage.IsSuccessStatusCode) throw new Exception(responseMessage.ReasonPhrase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task CreateFollowUpComment(PCRBFollowUpComment comment) {
|
||||||
|
if (comment is null) throw new ArgumentNullException("comment up cannot be null");
|
||||||
|
|
||||||
|
HttpClient httpClient = _httpClientFactory.CreateClient("API");
|
||||||
|
|
||||||
|
HttpRequestMessage requestMessage = new(HttpMethod.Post, $"pcrb/followUpComment") {
|
||||||
|
Content = new StringContent(JsonSerializer.Serialize(comment),
|
||||||
|
Encoding.UTF8,
|
||||||
|
"application/json")
|
||||||
|
};
|
||||||
|
|
||||||
|
HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage);
|
||||||
|
|
||||||
|
if (!responseMessage.IsSuccessStatusCode)
|
||||||
|
throw new Exception(responseMessage.ReasonPhrase);
|
||||||
|
|
||||||
|
await GetFollowUpCommentsByPlanNumber(comment.PlanNumber, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<PCRBFollowUpComment>> GetFollowUpCommentsByPlanNumber(int planNumber, bool bypassCache) {
|
||||||
|
if (planNumber <= 0) throw new ArgumentException($"{planNumber} is not a valid PCRB Plan#");
|
||||||
|
|
||||||
|
IEnumerable<PCRBFollowUpComment>? comments = null;
|
||||||
|
if (!bypassCache)
|
||||||
|
comments = _cache.Get<IEnumerable<PCRBFollowUpComment>>($"pcrbFollowUpComments{planNumber}");
|
||||||
|
|
||||||
|
if (comments is null) {
|
||||||
|
HttpClient httpClient = _httpClientFactory.CreateClient("API");
|
||||||
|
|
||||||
|
HttpRequestMessage requestMessage =
|
||||||
|
new(HttpMethod.Get, $"pcrb/followUpComments?planNumber={planNumber}&bypassCache={bypassCache}");
|
||||||
|
|
||||||
|
HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage);
|
||||||
|
|
||||||
|
if (responseMessage.IsSuccessStatusCode) {
|
||||||
|
string responseContent = await responseMessage.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
JsonSerializerOptions jsonSerializerOptions = new() {
|
||||||
|
PropertyNameCaseInsensitive = true
|
||||||
|
};
|
||||||
|
|
||||||
|
comments = JsonSerializer.Deserialize<IEnumerable<PCRBFollowUpComment>>(responseContent, jsonSerializerOptions) ??
|
||||||
|
new List<PCRBFollowUpComment>();
|
||||||
|
|
||||||
|
if (comments.Count() > 0) {
|
||||||
|
foreach (PCRBFollowUpComment comment in comments)
|
||||||
|
comment.User = await _userService.GetUserByUserId(comment.UserID);
|
||||||
|
|
||||||
|
_cache.Set($"pcrbFollowUpComments{planNumber}", comments, DateTimeOffset.Now.AddHours(1));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Exception(responseMessage.ReasonPhrase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return comments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpdateFollowUpComment(PCRBFollowUpComment comment) {
|
||||||
|
if (comment is null) throw new ArgumentNullException("comment up cannot be null");
|
||||||
|
|
||||||
|
HttpClient httpClient = _httpClientFactory.CreateClient("API");
|
||||||
|
|
||||||
|
HttpRequestMessage requestMessage = new(HttpMethod.Put, $"pcrb/followUpComment") {
|
||||||
|
Content = new StringContent(JsonSerializer.Serialize(comment),
|
||||||
|
Encoding.UTF8,
|
||||||
|
"application/json")
|
||||||
|
};
|
||||||
|
|
||||||
|
HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage);
|
||||||
|
|
||||||
|
if (!responseMessage.IsSuccessStatusCode)
|
||||||
|
throw new Exception(responseMessage.ReasonPhrase);
|
||||||
|
|
||||||
|
await GetFollowUpCommentsByPlanNumber(comment.PlanNumber, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteFollowUpComment(int id) {
|
||||||
|
if (id <= 0) throw new ArgumentException($"{id} is not a valid PCRB follow up comment ID");
|
||||||
|
|
||||||
|
HttpClient httpClient = _httpClientFactory.CreateClient("API");
|
||||||
|
|
||||||
|
HttpRequestMessage requestMessage = new(HttpMethod.Delete, $"pcrb/followUpComment?id={id}");
|
||||||
|
|
||||||
|
HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage);
|
||||||
|
|
||||||
|
if (!responseMessage.IsSuccessStatusCode) throw new Exception(responseMessage.ReasonPhrase);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ public class ApiHttpClientHandler : DelegatingHandler {
|
|||||||
string? redirectUrl = _cache.Get<string>("redirectUrl");
|
string? redirectUrl = _cache.Get<string>("redirectUrl");
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(redirectUrl)) {
|
if (!string.IsNullOrWhiteSpace(redirectUrl)) {
|
||||||
_navigationManager.NavigateTo($"login/{redirectUrl}");
|
_navigationManager.NavigateTo($"login?redirectPath={redirectUrl}");
|
||||||
} else {
|
} else {
|
||||||
_navigationManager.NavigateTo("login");
|
_navigationManager.NavigateTo("login");
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,21 @@ public class PCRB {
|
|||||||
"PCR1",
|
"PCR1",
|
||||||
"PCR2",
|
"PCR2",
|
||||||
"PCR3",
|
"PCR3",
|
||||||
"Complete"
|
"Complete",
|
||||||
|
"Follow Up",
|
||||||
|
"Closed"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public enum StagesEnum {
|
||||||
|
Draft = 0,
|
||||||
|
PCR1 = 1,
|
||||||
|
PCR2 = 2,
|
||||||
|
PCR3 = 3,
|
||||||
|
Complete = 4,
|
||||||
|
FollowUp = 5,
|
||||||
|
Closed = 6
|
||||||
|
}
|
||||||
|
|
||||||
public int PlanNumber { get; set; }
|
public int PlanNumber { get; set; }
|
||||||
public int OwnerID { get; set; }
|
public int OwnerID { get; set; }
|
||||||
public string OwnerName { get; set; } = "";
|
public string OwnerName { get; set; } = "";
|
||||||
@ -24,4 +36,5 @@ public class PCRB {
|
|||||||
public DateTime LastUpdateDate { get; set; } = DateTimeUtilities.MIN_DT;
|
public DateTime LastUpdateDate { get; set; } = DateTimeUtilities.MIN_DT;
|
||||||
public DateTime ClosedDate { get; set; } = DateTimeUtilities.MAX_DT;
|
public DateTime ClosedDate { get; set; } = DateTimeUtilities.MAX_DT;
|
||||||
public string Type { get; set; } = "";
|
public string Type { get; set; } = "";
|
||||||
|
public IEnumerable<PCRBFollowUp> FollowUps { get; set; } = new List<PCRBFollowUp>();
|
||||||
}
|
}
|
@ -9,6 +9,7 @@ public class PCRBFollowUp {
|
|||||||
public required DateTime FollowUpDate { get; set; }
|
public required DateTime FollowUpDate { get; set; }
|
||||||
public bool IsComplete { get; set; } = false;
|
public bool IsComplete { get; set; } = false;
|
||||||
public bool IsDeleted { get; set; } = false;
|
public bool IsDeleted { get; set; } = false;
|
||||||
|
public bool IsPendingApproval { get; set; } = false;
|
||||||
public DateTime CompletedDate { get; set; } = DateTimeUtilities.MAX_DT;
|
public DateTime CompletedDate { get; set; } = DateTimeUtilities.MAX_DT;
|
||||||
public string Comments { get; set; } = string.Empty;
|
public DateTime UpdateDate { get; set; } = DateTime.Now;
|
||||||
}
|
}
|
||||||
|
13
MesaFabApproval.Shared/Models/PCRBFollowUpComment.cs
Normal file
13
MesaFabApproval.Shared/Models/PCRBFollowUpComment.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using MesaFabApproval.Shared.Utilities;
|
||||||
|
|
||||||
|
namespace MesaFabApproval.Shared.Models;
|
||||||
|
|
||||||
|
public class PCRBFollowUpComment {
|
||||||
|
public int ID { get; set; }
|
||||||
|
public required int PlanNumber { get; set; }
|
||||||
|
public required int FollowUpID { get; set; }
|
||||||
|
public DateTime CommentDate { get; set; } = DateTime.Now;
|
||||||
|
public required int UserID { get; set; }
|
||||||
|
public User? User { get; set; }
|
||||||
|
public string Comment { get; set; } = string.Empty;
|
||||||
|
}
|
@ -2,5 +2,8 @@
|
|||||||
|
|
||||||
public class PCRBNotification {
|
public class PCRBNotification {
|
||||||
public required string Message { get; set; }
|
public required string Message { get; set; }
|
||||||
|
public string? Subject { get; set; }
|
||||||
public required PCRB PCRB { get; set; }
|
public required PCRB PCRB { get; set; }
|
||||||
|
public Approval? Approval { get; set; }
|
||||||
|
public bool NotifyQaPreApprover { get; set; } = false;
|
||||||
}
|
}
|
Reference in New Issue
Block a user