Switched to standard MonIn library

This commit is contained in:
Chase Tucker 2024-04-09 10:44:57 -07:00
parent 794b616293
commit 156dee0751
22 changed files with 539 additions and 345 deletions

View File

@ -29,9 +29,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Autofac.Extras.Quartz" Version="10.0.0" />
<PackageReference Include="Dapper" Version="2.1.28" />
<PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="Dapper.Contrib" Version="2.0.78" />
<PackageReference Include="Infineon.Monitoring.MonA" Version="3.0.1" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.2" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />

View File

@ -1,9 +0,0 @@
namespace FabApprovalWorkerService.Models;
public class MonInMetricRequest
{
public required string resource { get; set; }
public required DateTime dateTime { get; set; }
public required string metricName { get; set; }
public required double metricValue { get; set; }
}

View File

@ -1,9 +0,0 @@
namespace FabApprovalWorkerService.Models;
public class RawMonInStatusRequest
{
public required string resource { get; set; }
public required DateTime dateTime { get; set; }
public required string statusName { get; set; }
public required string statusValue { get; set; }
}

View File

@ -1,10 +0,0 @@
namespace FabApprovalWorkerService.Models;
public enum StatusValue {
Up,
Ok,
Warning,
Critical,
Down,
Unknown
}

View File

@ -1,12 +0,0 @@
using Dapper.Contrib.Extensions;
namespace FabApprovalWorkerService.Models;
[Table("TrainingAssignment")]
public class TrainingAssignment {
[Key]
public int ID { get; set; }
public int TrainingID { get; set; }
public bool Status { get; set; } = false;
public bool Deleted { get; set; } = false;
public DateTime DeletedDate { get; set; }
}

View File

@ -17,7 +17,7 @@ builder.Logging.AddNLog();
builder.Services.AddHttpClient();
builder.Services.AddScoped<IDbConnectionService, DbConnectionService>();
builder.Services.AddScoped<IMonInWorkerClient, MonInWorkerClient>();
builder.Services.AddScoped<IMonInClient, MonInClient>();
builder.Services.AddScoped<IDalService, DalService>();
builder.Services.AddScoped<SmtpClient>((serviceProvider) => {
return new SmtpClient("mailrelay-external.infineon.com");
@ -27,6 +27,7 @@ builder.Services.AddScoped<ISmtpService, SmtpService>();
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddScoped<IECNService, ECNService>();
builder.Services.AddScoped<ITrainingService, TrainingService>();
builder.Services.AddQuartz(q => {
JobKey pendingOOOStatusJob = new JobKey("Pending OOO status job");
@ -46,7 +47,7 @@ builder.Services.AddQuartz(q => {
q.AddTrigger(opts => opts
.ForJob(expiredOOOStatusJob)
.WithIdentity("Expired OOO status trigger")
.WithCronSchedule(CronScheduleBuilder.DailyAtHourAndMinute(0, 0))
.WithCronSchedule(CronScheduleBuilder.DailyAtHourAndMinute(10, 52))
);
JobKey expiringTECNJob = new JobKey("Expiring TECN job");
@ -56,11 +57,17 @@ builder.Services.AddQuartz(q => {
q.AddTrigger(opts => opts
.ForJob(expiringTECNJob)
.WithIdentity("Expiring TECN trigger")
.WithSimpleSchedule(x => x
.WithIntervalInMinutes(10)
.RepeatForever()
)
.StartNow()
.WithCronSchedule(CronScheduleBuilder.DailyAtHourAndMinute(6, 0))
);
JobKey expiredTECNJob = new JobKey("Expired TECN job");
q.AddJob<ExpiredTECNWorker>(opts => opts
.WithIdentity(expiredTECNJob)
);
q.AddTrigger(opts => opts
.ForJob(expiredTECNJob)
.WithIdentity("Expired TECN trigger")
.WithCronSchedule(CronScheduleBuilder.DailyAtHourAndMinute(6, 0))
);
});

View File

@ -23,21 +23,30 @@ public class ECNService : IECNService {
try {
_logger.LogInformation("Attempting to get all TECNs expired in the last day");
string today = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
string yesterday = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd HH:mm:ss");
DateTime today = DateTime.Now.Date;
DateTime tomorrow = DateTime.Now.Date.AddDays(1);
StringBuilder queryBuilder = new StringBuilder();
queryBuilder.Append("select ECNNumber, IsTECN, ExpirationDate, ExtensionDate, OriginatorID, Title ");
queryBuilder.Append($"from ECN where IsTECN = 1 and ");
queryBuilder.Append($"ExpirationDate between '{yesterday}' ");
queryBuilder.Append($"and '{today}'");
queryBuilder.Append("Cancelled = 0 and Deleted = 0 ");
queryBuilder.Append("and (CloseDate IS NULL or CloseDate = '');");
IEnumerable<ECN> expiredTecns = (await _dalService.QueryAsync<ECN>(queryBuilder.ToString()));
IEnumerable<ECN> activeTecns = await _dalService.QueryAsync<ECN>(queryBuilder.ToString());
_logger.LogInformation($"There are {activeTecns.Count()} active TECNs");
IEnumerable<ECN> expiredTecns = activeTecns.Where(e => ((e.ExpirationDate < tomorrow) && (e.ExpirationDate >= today)) ||
((e.ExtensionDate < tomorrow) && (e.ExtensionDate >= today)));
_logger.LogInformation($"There are {expiredTecns.Count()} TECNs with an expiration date or extension date today");
IEnumerable<ECN> expiredTecnsNotExtended = expiredTecns
.Where(e => e.ExtensionDate < DateTime.Now)
.Where(e => !(e.ExtensionDate >= tomorrow))
.ToList();
_logger.LogInformation($"There are {expiredTecnsNotExtended.Count()} TECNs expiring today");
return expiredTecnsNotExtended;
} catch (Exception ex) {
StringBuilder errMsgBuilder = new();
@ -52,21 +61,30 @@ public class ECNService : IECNService {
try {
_logger.LogInformation("Attempting to get all TECNs expiring in the next five days");
string today = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
string fiveDaysFromToday = DateTime.Now.AddDays(5).ToString("yyyy-MM-dd HH:mm:ss");
DateTime tomorrow = DateTime.Now.AddDays(1).Date;
DateTime fiveDaysFromToday = DateTime.Now.AddDays(5).Date;
StringBuilder queryBuilder = new StringBuilder();
queryBuilder.Append("select * from ECN ");
queryBuilder.Append($"where IsTECN = 1 and ");
queryBuilder.Append($"ExpirationDate between '{today}' ");
queryBuilder.Append($"and '{fiveDaysFromToday}';");
queryBuilder.Append("Cancelled = 0 and Deleted = 0 ");
queryBuilder.Append("and (CloseDate IS NULL or CloseDate = '');");
IEnumerable<ECN> expiringTecns = (await _dalService.QueryAsync<ECN>(queryBuilder.ToString()));
IEnumerable<ECN> activeTecns = (await _dalService.QueryAsync<ECN>(queryBuilder.ToString()));
_logger.LogInformation($"There are {activeTecns.Count()} active TECNs");
IEnumerable<ECN> expiringTecns = activeTecns.Where(e => ((e.ExpirationDate >= tomorrow) && (e.ExpirationDate <= fiveDaysFromToday)) ||
((e.ExtensionDate >= tomorrow) && (e.ExtensionDate <= fiveDaysFromToday)));
_logger.LogInformation($"There are {expiringTecns.Count()} TECNs with an expiration date or extension date in the next 5 days");
IEnumerable<ECN> expiringTecnsNotExtended = expiringTecns
.Where(e => e.ExtensionDate <= DateTime.Now.AddDays(5))
.Where(e => !(e.ExtensionDate > fiveDaysFromToday))
.ToList();
_logger.LogInformation($"There are {expiringTecnsNotExtended.Count()} TECNs expiring in the next five days");
return expiringTecnsNotExtended;
} catch (Exception ex) {
StringBuilder errMsgBuilder = new();

View File

@ -0,0 +1,58 @@
using Infineon.Monitoring.MonA;
namespace FabApprovalWorkerService.Services;
public interface IMonInClient {
void PostMetric(string metricName, double metricValue);
void PostStatus(string statusName, State state);
}
public class MonInClient : IMonInClient {
private readonly ILogger<MonInClient> _logger;
private readonly string _site;
private readonly string _resource;
public MonInClient(ILogger<MonInClient> logger) {
_logger = logger ??
throw new ArgumentNullException("ILogger not injected");
_site = Environment.GetEnvironmentVariable("MonInSite") ??
throw new ArgumentNullException("MonInSite environment variable not found");
_resource = Environment.GetEnvironmentVariable("FabApprovalWorkerServiceMonInResource") ??
throw new ArgumentNullException("FabApprovalWorkerServiceMonInResource environment variable not found");
}
public void PostMetric(string metricName, double metricValue) {
try {
_logger.LogInformation("Attempting to send MonIn metric request for resource {0} with name {1} and value {2}",
_resource,
metricName,
metricValue);
MonIn.GetInstance().SendPerformanceMessage(_site, _resource, metricName, metricValue);
} catch (Exception ex) {
_logger.LogError("An exception occurred when attempting to send MonIn metric request for resource {0} with name {1} and value {2}. Exception: {3}",
_resource,
metricName,
metricValue,
ex.Message);
}
}
public void PostStatus(string statusName, State state) {
try {
_logger.LogInformation("Attempting to send MonIn status request for resource {0} with name {1} and value {2}",
_resource,
statusName,
state.ToString());
MonIn.GetInstance().SendStatus(_site, _resource, statusName, state);
} catch (Exception ex) {
_logger.LogError("An exception occurred when attempting to send MonIn status request for resource {0} with name {1} and value {2}. Exception: {3}",
_resource,
statusName,
state.ToString(),
ex.Message);
}
}
}

View File

@ -1,181 +0,0 @@
using System.Text;
using System.Text.Json;
using FabApprovalWorkerService.Models;
using static System.Net.Mime.MediaTypeNames;
namespace FabApprovalWorkerService.Services;
public interface IMonInWorkerClient {
void PostAverage(string metricName, double metricValue);
void PostCount(string metricName, double metricValue);
void PostStatus(string statusName, StatusValue statusValue);
}
public class MonInWorkerClient : IMonInWorkerClient {
private readonly IHttpClientFactory _httpClientFactory;
private readonly IConfiguration _config;
private readonly ILogger<MonInWorkerClient> _logger;
private readonly string _baseUrl;
private readonly int _retryLimit = -1;
private readonly int _backoffInSeconds = -1;
private readonly string _resource;
public MonInWorkerClient(IHttpClientFactory httpClientFactory,
IConfiguration config,
ILogger<MonInWorkerClient> logger) {
_httpClientFactory = httpClientFactory;
if (_httpClientFactory is null) throw new ArgumentNullException("IHttpClientFactory not injected");
_config = config ??
throw new ArgumentNullException("IConfiguration not injected");
_logger = logger ??
throw new ArgumentNullException("ILogger not injected");
_baseUrl = Environment.GetEnvironmentVariable("MonInWorkerUrl") ??
throw new ArgumentNullException("MonInWorkerUrl environment variable not found");
if (!Int32.TryParse(Environment.GetEnvironmentVariable("MonInRetries"), out _retryLimit))
throw new ArgumentNullException("Valid MonInRetries environment variable not found");
if (!Int32.TryParse(Environment.GetEnvironmentVariable("MonInBackoffSeconds"), out _backoffInSeconds))
throw new ArgumentNullException("Valid MonInBackoffSeconds environment varialbe not found");
_resource = Environment.GetEnvironmentVariable("FabApprovalWorkerServiceMonInResource") ??
throw new ArgumentNullException("FabApprovalWorkerServiceMonInResource environment variable not found");
}
public async void PostStatus(string statusName, StatusValue statusValue) {
string url = _baseUrl + "status";
_logger.LogInformation("Attempting to send MonIn status request for resource {0} with name {1} and value {2} to url {3}",
_resource,
statusName,
statusValue.ToString(),
url);
try {
bool success = false;
int retries = _retryLimit;
while (!success && retries > 0) {
Task.Delay(TimeSpan.FromSeconds((_retryLimit - retries) * _backoffInSeconds)).Wait();
HttpClient httpClient = _httpClientFactory.CreateClient();
RawMonInStatusRequest statusRequest = new RawMonInStatusRequest() {
resource = _resource,
dateTime = DateTime.Now,
statusName = statusName,
statusValue = statusValue.ToString()
};
StringContent statusRequestJson = new StringContent(JsonSerializer.Serialize(statusRequest),
Encoding.UTF8,
Application.Json);
using HttpResponseMessage httpResponseMessage =
await httpClient.PostAsync(url, statusRequestJson);
success = httpResponseMessage.IsSuccessStatusCode;
retries--;
}
} catch (Exception ex) {
_logger.LogError("An exception occurred when attempting to send MonIn status request for resource {0} with name {1} and value {2} to url {3}. Exception: {4}",
_resource,
statusName,
statusValue.ToString(),
url,
ex.Message);
}
}
public async void PostCount(string metricName, double metricValue) {
string url = _baseUrl + "count";
_logger.LogInformation("Attempting to send MonIn count request for resource {0} with name {1} and value {2} to url {3}",
_resource,
metricName,
metricValue,
url);
try {
bool success = false;
int retries = _retryLimit;
while (!success && retries > 0) {
Task.Delay(TimeSpan.FromSeconds((_retryLimit - retries) * _backoffInSeconds)).Wait();
HttpClient httpClient = _httpClientFactory.CreateClient();
MonInMetricRequest metricRequest = new MonInMetricRequest() {
resource = _resource,
dateTime = DateTime.Now,
metricName = metricName,
metricValue = metricValue
};
StringContent metricRequestJson = new StringContent(JsonSerializer.Serialize(metricRequest),
Encoding.UTF8,
Application.Json);
using HttpResponseMessage httpResponseMessage =
await httpClient.PostAsync(url, metricRequestJson);
success = httpResponseMessage.IsSuccessStatusCode;
retries--;
}
} catch (Exception ex) {
_logger.LogError("An exception occurred when attempting to send MonIn count request for resource {0} with name {1} and value {2} to url {3}. Exception: {4}",
_resource,
metricName,
metricValue,
url,
ex.Message);
}
}
public async void PostAverage(string metricName, double metricValue) {
string url = _baseUrl + "average";
_logger.LogInformation("Attempting to send MonIn average request for resource {0} with name {1} and value {2} to url {3}",
_resource,
metricName,
metricValue,
url);
try {
bool success = false;
int retries = _retryLimit;
while (!success && retries > 0) {
Task.Delay(TimeSpan.FromSeconds((_retryLimit - retries) * _backoffInSeconds)).Wait();
HttpClient httpClient = _httpClientFactory.CreateClient();
MonInMetricRequest metricRequest = new MonInMetricRequest() {
resource = _resource,
dateTime = DateTime.Now,
metricName = metricName,
metricValue = metricValue
};
StringContent metricRequestJson = new StringContent(JsonSerializer.Serialize(metricRequest),
Encoding.UTF8,
Application.Json);
using HttpResponseMessage httpResponseMessage =
await httpClient.PostAsync(url, metricRequestJson);
success = httpResponseMessage.IsSuccessStatusCode;
retries--;
}
} catch (Exception ex) {
_logger.LogError("An exception occurred when attempting to send MonIn average request for resource {0} with name {1} and value {2} to url {3}. Exception: {4}",
_resource,
metricName,
metricValue,
url,
ex.Message);
}
}
}

View File

@ -6,6 +6,7 @@ namespace FabApprovalWorkerService.Services;
public interface ITrainingService {
Task<IEnumerable<int>> GetTrainingIdsForECN(int ecnNumber);
Task MarkTrainingAsComplete(int trainingId);
Task DeleteTrainingAssignment(int trainingId);
Task<IEnumerable<int>> GetTrainingAssignmentIdsForTraining(int trainingId);
Task DeleteDocAssignment(int trainingAssignmentId);
@ -30,7 +31,7 @@ public class TrainingService : ITrainingService {
StringBuilder queryBuilder = new();
queryBuilder.Append($"update TrainingDocAcks set Deleted = 1, ");
queryBuilder.Append($"DeletedDate = {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} ");
queryBuilder.Append($"DeletedDate = '{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}' ");
queryBuilder.Append($"where TrainingAssignmentID = {trainingAssignmentId} and Reviewed = 0;");
await _dalService.ExecuteAsync(queryBuilder.ToString());
@ -51,7 +52,7 @@ public class TrainingService : ITrainingService {
StringBuilder queryBuilder = new();
queryBuilder.Append($"update TrainingAssignments set Deleted = 1, ");
queryBuilder.Append($"DeletedDate = {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} ");
queryBuilder.Append($"DeletedDate = '{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}' ");
queryBuilder.Append($"where TrainingID = {trainingId} and status = 0;");
await _dalService.ExecuteAsync(queryBuilder.ToString());
@ -64,6 +65,27 @@ public class TrainingService : ITrainingService {
}
}
public async Task MarkTrainingAsComplete(int trainingId) {
if (trainingId <= 0) throw new ArgumentException($"Invalid training id: {trainingId}");
try {
_logger.LogInformation($"Attempting to mark training {trainingId} as complete");
StringBuilder queryBuilder = new();
queryBuilder.Append($"update Training set Status = 1, ");
queryBuilder.Append($"CompletedDate = '{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}' ");
queryBuilder.Append($"where TrainingID = {trainingId};");
await _dalService.ExecuteAsync(queryBuilder.ToString());
} catch (Exception ex) {
StringBuilder errMsgBuilder = new();
errMsgBuilder.Append($"An exception occurred when attempting to mark training {trainingId} ");
errMsgBuilder.Append($"as complete. Exception: {ex.Message}");
_logger.LogError(errMsgBuilder.ToString());
throw;
}
}
public async Task<IEnumerable<int>> GetTrainingAssignmentIdsForTraining(int trainingId) {
if (trainingId <= 0) throw new ArgumentException($"Invalid trainingID: {trainingId}");

View File

@ -44,7 +44,7 @@ public class UserService : IUserService {
StringBuilder queryBuilder = new();
queryBuilder.Append("select * from Users where OOO = 1 and IsActive = 1 and ");
queryBuilder.Append($"OOOExpirationDate <= '{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}';");
queryBuilder.Append($"OOOExpirationDate <= '{DateTime.Now.Date.ToString("yyyy-MM-dd HH:mm:ss")}';");
return (await _dalService.QueryAsync<User>(queryBuilder.ToString())).ToList();
} catch (Exception ex) {
@ -60,7 +60,7 @@ public class UserService : IUserService {
StringBuilder queryBuilder = new();
queryBuilder.Append("select * from OOOTemp where Processed = 0 and ");
queryBuilder.Append($"OOOStartDate <= '{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}';");
queryBuilder.Append($"OOOStartDate <= '{DateTime.Now.Date.ToString("yyyy-MM-dd HH:mm:ss")}';");
return (await _dalService.QueryAsync<OOOTemp>(queryBuilder.ToString())).ToList();
} catch (Exception ex) {
@ -92,7 +92,7 @@ public class UserService : IUserService {
public async Task<bool> IsDelegatorAlreadyDelegatedTo(int userId) {
try {
_logger.LogInformation($"Attempting to determine if user {userId} is already OOO.");
_logger.LogInformation($"Attempting to determine if user {userId} is already a delegate.");
if (userId <= 0) {
_logger.LogInformation($"DelegatedTo is {userId}, which is not an active user Id");
@ -127,7 +127,7 @@ public class UserService : IUserService {
foreach (UserSubRole role in userSubRoles) {
queryBuilder.Clear();
queryBuilder.Append("insert into OOODelegatedRoles (UserID, DelegatedSubRoleID, InsertTimeStamp, Active) ");
queryBuilder.Append($"values ({userId}, {role.SubRoleID}, '{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}', 1);");
queryBuilder.Append($"values ({userId}, {role.SubRoleID}, '{DateTime.Now.Date.ToString("yyyy-MM-dd HH:mm:ss")}', 1);");
await _dalService.ExecuteAsync(queryBuilder.ToString());
}
@ -196,8 +196,8 @@ public class UserService : IUserService {
if (userId <= 0)
throw new ArgumentException($"User Id {userId} is not a valid user Id");
if (delegatedUserId <= 0)
throw new ArgumentException($"Delegated user Id {delegatedUserId} is not a valid user Id");
if (delegatedUserId > 0) {
_logger.LogInformation($"User {userId} delegated sub roles to {delegatedUserId}");
StringBuilder queryBuilder = new StringBuilder();
queryBuilder.Append("select SubRoleID from OOODelegatedRoles O inner join UserSubRole U ");
@ -214,6 +214,9 @@ public class UserService : IUserService {
await _dalService.ExecuteAsync(queryBuilder.ToString());
}
} else {
_logger.LogInformation($"User {userId} had no delegated sub roles");
}
return true;
} catch (Exception ex) {
@ -256,8 +259,8 @@ public class UserService : IUserService {
if (userId <= 0)
throw new ArgumentException($"User Id {userId} is not a valid user Id");
if (delegatedUserId <= 0)
throw new ArgumentException($"Delegated user Id {delegatedUserId} is not a valid user Id");
if (delegatedUserId > 0) {
_logger.LogInformation($"User {userId} delegated approvals to {delegatedUserId}");
StringBuilder queryBuilder = new StringBuilder();
@ -276,6 +279,9 @@ public class UserService : IUserService {
await _dalService.ExecuteAsync(queryBuilder.ToString());
}
} else {
_logger.LogInformation($"User {userId} had not delegated approvals");
}
return true;
} catch (Exception ex) {
@ -332,7 +338,7 @@ public class UserService : IUserService {
_logger.LogInformation($"Attempting to set OOOTemp {oooTemp.ID} Processed to {oooTemp.Processed}");
string sql = $"update OOOTemp set Processed = {oooTemp.Processed} where ID = {oooTemp.ID}";
string sql = $"update OOOTemp set Processed = {Convert.ToInt32(oooTemp.Processed)} where ID = {oooTemp.ID}";
return (await _dalService.ExecuteAsync(sql)) > 0;
} catch (Exception ex) {

View File

@ -1,18 +1,20 @@
using FabApprovalWorkerService.Models;
using Infineon.Monitoring.MonA;
namespace FabApprovalWorkerService.Services;
public class WindowsService : BackgroundService {
private readonly ILogger<WindowsService> _logger;
private readonly IMonInWorkerClient _monInClient;
private readonly IMonInClient _monInClient;
public WindowsService(ILogger<WindowsService> logger,
IServiceProvider serviceProvider) {
_logger = logger ??
throw new ArgumentNullException("ILogger not injected");
using (IServiceScope scope = serviceProvider.CreateScope()) {
_monInClient = scope.ServiceProvider.GetService<IMonInWorkerClient>() ??
throw new ArgumentNullException("IMonInWorkerClient not injected");
_monInClient = scope.ServiceProvider.GetService<IMonInClient>() ??
throw new ArgumentNullException("IMonInClient not injected");
}
}
@ -21,18 +23,18 @@ public class WindowsService : BackgroundService {
try {
while (!stoppingToken.IsCancellationRequested) {
await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
_monInClient.PostStatus("WindowsService", State.Ok);
_monInClient.PostStatus("WindowsService", StatusValue.Ok);
await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
}
} catch (OperationCanceledException) {
_logger.LogError("The Windows service has been stopped");
_monInClient.PostStatus("WindowsService", StatusValue.Critical);
_monInClient.PostStatus("WindowsService", State.Critical);
} catch (Exception ex) {
_logger.LogError($"An exception occurred when running Windows Service. Exception: {ex.Message}");
_monInClient.PostStatus("WindowsService", StatusValue.Critical);
_monInClient.PostStatus("WindowsService", State.Critical);
Environment.Exit(1);
}

View File

@ -3,14 +3,22 @@ drop table if exists ECN;
create table ECN (
ECNNumber integer primary key not null,
IsTECN integer default 0,
ExpirationDate text,
ExtensionDate text,
ExpirationDate text default '',
ExtensionDate text default '',
OriginatorID integer not null,
Title text not null
Title text not null,
Deleted integer default 0,
Cancelled integer default 0,
CloseDate text default ''
);
insert into ECN (ECNNumber, IsTECN, ExpirationDate, ExtensionDate, OriginatorID, Title)
values (1, 0, '2024-04-06 00:00:00', null, 1, 'title1'),
(2, 1, '2024-04-04 00:00:00', null, 6, 'title2'),
values (1, 1, '2024-04-05 00:00:00', null, 1, 'title1'),
(2, 1, '2024-04-04 12:00:00', null, 6, 'title2'),
(3, 1, '2024-06-01 00:00:00', null, 4, 'title3'),
(4, 1, '2024-04-03 00:00:00', '2024-06-01 00:00:00', 3, 'title4')
(4, 1, '2024-02-05 00:00:00', '2024-04-05 09:00:00', 3, 'title4'),
(5, 1, '2024-06-01 00:00:00', null, 4, 'title3'),
(6, 1, '2024-04-07 00:00:00', null, 9, 'title6'),
(7, 1, '2024-04-07 00:00:00', '2024-06-01 00:00:00', 13, 'title9'),
(8, 1, '2024-02-05 00:00:00', '2024-04-07 09:00:00', 3, 'title4'),
(9, 1, '2024-02-05 00:00:00', '2024-04-06 09:00:00', 3, 'title4')

View File

@ -0,0 +1,39 @@
drop table if exists Training;
create table Training (
TrainingID integer primary key,
ECN integer not null,
Status integer default 0,
CompletedDate text
);
insert into Training (ECN)
values (1), (2), (3), (4), (5), (6), (7), (8), (9);
drop table if exists TrainingAssignments;
create table TrainingAssignments (
ID integer primary key,
TrainingID integer not null,
Deleted integer default 0,
status integer default 0,
DeletedDate text
);
insert into TrainingAssignments (TrainingID)
values (1), (1), (2), (2), (3), (3), (4), (4), (5), (5), (6), (6),
(7), (7), (8), (8), (9), (9);
drop table if exists TrainingDocAcks;
create table TrainingDocAcks (
ID integer primary key,
TrainingAssignmentID integer not null,
Reviewed integer default 0,
Deleted integer default 0,
DeletedDate text
);
insert into TrainingDocAcks (TrainingAssignmentID)
values (1), (1), (2), (2), (3), (3), (4), (4), (5), (5), (6), (6),
(7), (7), (8), (8), (9), (9);

View File

@ -6,4 +6,5 @@ sqlite3 D:\FabApprovalWorkerService\LocalDb.db < .\CreateOOODelegatedRolesTable.
sqlite3 D:\FabApprovalWorkerService\LocalDb.db < .\CreateApprovalTable.sql
sqlite3 D:\FabApprovalWorkerService\LocalDb.db < .\CreateECNTable.sql
sqlite3 D:\FabApprovalWorkerService\LocalDb.db < .\CreateTECNNotificationUsersTable.sql
sqlite3 D:\FabApprovalWorkerService\LocalDb.db < .\CreateTrainingTables.sql
pause

View File

@ -1,6 +1,8 @@
using FabApprovalWorkerService.Models;
using FabApprovalWorkerService.Services;
using Infineon.Monitoring.MonA;
using Quartz;
using System.Text;
@ -9,11 +11,11 @@ namespace FabApprovalWorkerService.Workers;
public sealed class ExpiredOOOStatusWorker : IJob {
private readonly ILogger<ExpiredOOOStatusWorker> _logger;
private readonly IMonInWorkerClient _monInClient;
private readonly IMonInClient _monInClient;
private readonly IUserService _userService;
public ExpiredOOOStatusWorker(ILogger<ExpiredOOOStatusWorker> logger,
IMonInWorkerClient monInClient,
IMonInClient monInClient,
IUserService userService) {
_logger = logger;
if (_logger is null)
@ -21,7 +23,7 @@ public sealed class ExpiredOOOStatusWorker : IJob {
_monInClient = monInClient;
if (_monInClient is null) {
throw new ArgumentNullException("IMonInWorkerClient not injected");
throw new ArgumentNullException("IMonInClient not injected");
}
_userService = userService;
@ -40,6 +42,8 @@ public sealed class ExpiredOOOStatusWorker : IJob {
List<User> expiredOOOUsers = await _userService.GetAllExpiredOOOUsersAsync();
_logger.LogInformation($"There are {expiredOOOUsers.Count()} OOO users expiring");
foreach (User user in expiredOOOUsers) {
bool approvalsRemoved = await _userService.RemoveDelegatedApprovalsForUser(user.UserID, user.DelegatedTo);
bool subRolesRemoved = await _userService.RemoveDelegatedUserSubRoles(user.UserID, user.DelegatedTo);
@ -67,12 +71,12 @@ public sealed class ExpiredOOOStatusWorker : IJob {
} finally {
DateTime end = DateTime.Now;
double latencyInMS = (end - start).TotalMilliseconds;
_monInClient.PostAverage(metricName + "Latency", latencyInMS);
_monInClient.PostMetric(metricName + "Latency", latencyInMS);
if (isInternalError) {
_monInClient.PostStatus(metricName, StatusValue.Critical);
_monInClient.PostStatus(metricName, State.Critical);
} else {
_monInClient.PostStatus(metricName, StatusValue.Ok);
_monInClient.PostStatus(metricName, State.Ok);
}
}
}

View File

@ -0,0 +1,109 @@
using FabApprovalWorkerService.Models;
using FabApprovalWorkerService.Services;
using Infineon.Monitoring.MonA;
using Quartz;
using System.Net.Mail;
using System.Text;
namespace FabApprovalWorkerService.Workers;
public class ExpiredTECNWorker : IJob {
private readonly ILogger<ExpiredTECNWorker> _logger;
private readonly IECNService _ecnService;
private readonly ITrainingService _trainingService;
private readonly IUserService _userService;
private readonly ISmtpService _smtpService;
private readonly IMonInClient _monInClient;
private readonly string _baseUrl;
public ExpiredTECNWorker(ILogger<ExpiredTECNWorker> logger,
IECNService ecnService,
ITrainingService trainingService,
IUserService userService,
ISmtpService smtpService,
IMonInClient monInClient) {
_logger = logger ??
throw new ArgumentNullException("ILogger not injected");
_ecnService = ecnService ??
throw new ArgumentNullException("IECNService not injected");
_trainingService = trainingService ??
throw new ArgumentNullException("ITrainingService not injected");
_userService = userService ??
throw new ArgumentNullException("IUserService not injected");
_smtpService = smtpService ??
throw new ArgumentNullException("ISmtpService not injected");
_monInClient = monInClient ??
throw new ArgumentNullException("IMonInClient not injected");
_baseUrl = Environment.GetEnvironmentVariable("FabApprovalBaseUrl") ??
throw new ArgumentNullException("FabApprovalBaseUrl environment variable not found");
}
public async Task Execute(IJobExecutionContext context) {
DateTime start = DateTime.Now;
bool isInternalError = false;
StringBuilder errorMessage = new();
string metricName = "ExpiredTECNWorker";
try {
_logger.LogInformation("Attempting to process expired TECNs");
List<ECN> expiredEcns = (await _ecnService.GetExpiredTECNs()).ToList();
List<MailAddress> tecnNotificationUserEmails = new();
if (expiredEcns.Any()) {
List<string> emails = (await _ecnService.GetTECNNotificationUserEmails()).ToList();
foreach (string email in emails) tecnNotificationUserEmails.Add(new MailAddress(email));
}
foreach (ECN ecn in expiredEcns) {
List<int> trainingIds = (await _trainingService.GetTrainingIdsForECN(ecn.ECNNumber)).ToList();
foreach (int trainingId in trainingIds) {
await _trainingService.DeleteTrainingAssignment(trainingId);
List<int> trainingAssignmentIds =
(await _trainingService.GetTrainingAssignmentIdsForTraining(trainingId)).ToList();
foreach (int assignmentId in trainingAssignmentIds) {
await _trainingService.DeleteDocAssignment(assignmentId);
}
await _trainingService.MarkTrainingAsComplete(trainingId);
}
string recipientEmail = await _userService.GetUserEmail(ecn.OriginatorID);
List<MailAddress> recipientEamils = new List<MailAddress>() {
new MailAddress(recipientEmail)
};
string subject = "Notice of Expired TECN";
StringBuilder bodyBuilder = new();
bodyBuilder.Append($"Good day, TECN# {ecn.ECNNumber} expired on {ecn.ExpirationDate.ToString("MMMM dd, yyyy")}. ");
bodyBuilder.Append($"<br />Review TECN <a href='{_baseUrl}/ECN/Edit?IssueID={ecn.ECNNumber}'> here. </a>");
await _smtpService.SendEmail(recipientEamils, tecnNotificationUserEmails, subject, bodyBuilder.ToString());
}
} catch (Exception ex) {
StringBuilder errMsgBuilder = new();
errMsgBuilder.Append("An exception occurred when attempting to process expired TECNs. ");
errMsgBuilder.Append($"Exception: {ex.Message}");
_logger.LogError(errMsgBuilder.ToString());
isInternalError = true;
} finally {
DateTime end = DateTime.Now;
double latencyInMS = (end - start).TotalMilliseconds;
_monInClient.PostMetric(metricName + "Latency", latencyInMS);
if (isInternalError) {
_monInClient.PostStatus(metricName, State.Critical);
} else {
_monInClient.PostStatus(metricName, State.Ok);
}
}
}
}

View File

@ -1,6 +1,8 @@
using FabApprovalWorkerService.Models;
using FabApprovalWorkerService.Services;
using Infineon.Monitoring.MonA;
using Quartz;
using System.Net.Mail;
@ -10,26 +12,29 @@ namespace FabApprovalWorkerService.Workers;
public class ExpiringTECNWorker : IJob {
private readonly ILogger<ExpiringTECNWorker> _logger;
private readonly IMonInWorkerClient _monInClient;
private readonly IMonInClient _monInClient;
private readonly IUserService _userService;
private readonly IECNService _ecnService;
private readonly ISmtpService _smtpService;
private readonly string _baseUrl;
public ExpiringTECNWorker(ILogger<ExpiringTECNWorker> logger,
IMonInWorkerClient monInClient,
IMonInClient monInClient,
IUserService userService,
IECNService ecnService,
ISmtpService smtpService) {
_logger = logger ??
throw new ArgumentNullException("ILogger not injected");
_monInClient = monInClient ??
throw new ArgumentNullException("IMonInWorkerClient not injected");
throw new ArgumentNullException("IMonInClient not injected");
_userService = userService ??
throw new ArgumentNullException("IUserService not injected");
_ecnService = ecnService ??
throw new ArgumentNullException("IECNService not injected");
_smtpService = smtpService ??
throw new ArgumentNullException("ISmtpService not injected");
_baseUrl = Environment.GetEnvironmentVariable("FabApprovalBaseUrl") ??
throw new ArgumentNullException("FabApprovalBaseUrl environment variable not found");
}
public async Task Execute(IJobExecutionContext context) {
@ -45,12 +50,15 @@ public class ExpiringTECNWorker : IJob {
_logger.LogInformation($"There are {expiringTECNs.Count()} TECNs expiring in the next 5 days");
IEnumerable<string> tecnNotificationUserEmails = new List<string>();
if (expiringTECNs.Any())
tecnNotificationUserEmails = await _ecnService.GetTECNNotificationUserEmails();
foreach (ECN eCN in expiringTECNs) {
string recipientEmail = await _userService.GetUserEmail(eCN.OriginatorID);
MailAddress recipientAddress = new MailAddress(recipientEmail);
List<MailAddress> recipientList = new () { recipientAddress };
IEnumerable<string> tecnNotificationUserEmails = await _ecnService.GetTECNNotificationUserEmails();
List<MailAddress> ccRecipientList = new();
foreach (string email in tecnNotificationUserEmails) {
ccRecipientList.Add(new MailAddress(email));
@ -59,10 +67,10 @@ public class ExpiringTECNWorker : IJob {
StringBuilder bodyBuilder = new();
bodyBuilder.Append($"Good day, TECN# {eCN.ECNNumber} will be expire on ");
bodyBuilder.Append($"{eCN.ExpirationDate.ToString("MMMM dd, yyyy")}. ");
bodyBuilder.Append($"<br /> Review TECN <a href='https://mesaapproval.mes.com/ECN/Edit?IssueID={eCN.ECNNumber}'> ");
bodyBuilder.Append($"<br /> Review TECN <a href='{_baseUrl}/ECN/Edit?IssueID={eCN.ECNNumber}'> ");
bodyBuilder.Append("here </a>");
string subject = $"Notice of expiring TECN - {eCN.Title}";
string subject = $"Notice of Expiring TECN - {eCN.Title}";
await _smtpService.SendEmail(recipientList, ccRecipientList, subject, bodyBuilder.ToString());
}
@ -75,12 +83,12 @@ public class ExpiringTECNWorker : IJob {
} finally {
DateTime end = DateTime.Now;
double latencyInMS = (end - start).TotalMilliseconds;
_monInClient.PostAverage(metricName + "Latency", latencyInMS);
_monInClient.PostMetric(metricName + "Latency", latencyInMS);
if (isInternalError) {
_monInClient.PostStatus(metricName, StatusValue.Critical);
_monInClient.PostStatus(metricName, State.Critical);
} else {
_monInClient.PostStatus(metricName, StatusValue.Ok);
_monInClient.PostStatus(metricName, State.Ok);
}
}
}

View File

@ -1,6 +1,8 @@
using FabApprovalWorkerService.Models;
using FabApprovalWorkerService.Services;
using Infineon.Monitoring.MonA;
using Quartz;
using System.Text;
@ -9,11 +11,11 @@ namespace FabApprovalWorkerService.Workers;
public sealed class PendingOOOStatusWorker : IJob {
private readonly ILogger<PendingOOOStatusWorker> _logger;
private readonly IMonInWorkerClient _monInClient;
private readonly IMonInClient _monInClient;
private readonly IUserService _userService;
public PendingOOOStatusWorker(ILogger<PendingOOOStatusWorker> logger,
IMonInWorkerClient monInClient,
IMonInClient monInClient,
IUserService userService) {
_logger = logger;
if (_logger is null)
@ -21,7 +23,7 @@ public sealed class PendingOOOStatusWorker : IJob {
_monInClient = monInClient;
if (_monInClient is null) {
throw new ArgumentNullException("IMonInWorkerClient not injected");
throw new ArgumentNullException("IMonInClient not injected");
}
_userService = userService;
@ -40,24 +42,26 @@ public sealed class PendingOOOStatusWorker : IJob {
List<OOOTemp> pendingOOOUsers = await _userService.GetAllPendingOOOUsersAsync();
_logger.LogInformation($"There are {pendingOOOUsers.Count()} pending OOO users");
foreach (OOOTemp oooTemp in pendingOOOUsers) {
Task<bool> userAlreadyOOO = _userService.IsUserAlreadyOOO(oooTemp.OOOUserID);
Task<bool> delegateAlreadyADelegate = _userService.IsDelegatorAlreadyDelegatedTo(oooTemp.DelegatedTo);
bool userAlreadyOOO = await _userService.IsUserAlreadyOOO(oooTemp.OOOUserID);
bool delegateAlreadyADelegate = await _userService.IsDelegatorAlreadyDelegatedTo(oooTemp.DelegatedTo);
if (!userAlreadyOOO.Result && !delegateAlreadyADelegate.Result) {
List<Task> enableOOOTasks = new();
enableOOOTasks.Add(_userService.InsertDelegatedRoles(oooTemp.OOOUserID));
enableOOOTasks.Add(_userService.DelegateUserSubRoles(oooTemp.OOOUserID, oooTemp.DelegatedTo));
enableOOOTasks.Add(_userService.DelegateApprovalsForUser(oooTemp.OOOUserID, oooTemp.DelegatedTo));
Task enableOOOTasksResult = Task.WhenAll(enableOOOTasks);
if (!userAlreadyOOO && !delegateAlreadyADelegate) {
await _userService.InsertDelegatedRoles(oooTemp.OOOUserID);
await _userService.DelegateUserSubRoles(oooTemp.OOOUserID, oooTemp.DelegatedTo);
await _userService.DelegateApprovalsForUser(oooTemp.OOOUserID, oooTemp.DelegatedTo);
if (enableOOOTasksResult.IsCompletedSuccessfully) {
bool userIsNowOOO = await _userService.FlagUserAsOOO(oooTemp);
if (userIsNowOOO) {
oooTemp.Processed = true;
await _userService.SetOOOTempProcessed(oooTemp);
}
}
} else if (userAlreadyOOO) {
_logger.LogInformation($"User {oooTemp.OOOUserID} is already OOO");
} else if (delegateAlreadyADelegate) {
_logger.LogInformation($"Delegate {oooTemp.DelegatedTo} is already a delegate");
}
}
@ -71,12 +75,12 @@ public sealed class PendingOOOStatusWorker : IJob {
} finally {
DateTime end = DateTime.Now;
double latencyInMS = (end - start).TotalMilliseconds;
_monInClient.PostAverage(metricName + "Latency", latencyInMS);
_monInClient.PostMetric(metricName + "Latency", latencyInMS);
if (isInternalError) {
_monInClient.PostStatus(metricName, StatusValue.Critical);
_monInClient.PostStatus(metricName, State.Critical);
} else {
_monInClient.PostStatus(metricName, StatusValue.Ok);
_monInClient.PostStatus(metricName, State.Ok);
}
}
}

View File

@ -115,21 +115,21 @@ internal class ECNServiceTests {
OriginatorID = 1,
Title = "title1",
IsTECN = true,
ExpirationDate = DateTime.Now.AddHours(-2)
ExpirationDate = DateTime.Now.Date.AddHours(2)
},
new ECN() {
ECNNumber = 2,
OriginatorID = 1,
Title = "title2",
IsTECN = true,
ExpirationDate = DateTime.Now.AddHours(-20)
ExpirationDate = DateTime.Now.Date.AddHours(20)
},
new ECN() {
ECNNumber = 3,
OriginatorID = 1,
Title = "title3",
IsTECN = true,
ExpirationDate = DateTime.Now.AddHours(-12)
ExpirationDate = DateTime.Now.Date.AddHours(12)
},
};
@ -186,22 +186,22 @@ internal class ECNServiceTests {
OriginatorID = 1,
Title = "title1",
IsTECN = true,
ExpirationDate = DateTime.Now.AddHours(-2)
ExpirationDate = DateTime.Now.Date.AddHours(2)
},
new ECN() {
ECNNumber = 2,
OriginatorID = 1,
Title = "title2",
IsTECN = true,
ExpirationDate = DateTime.Now.AddHours(-20)
ExpirationDate = DateTime.Now.Date.AddHours(20)
},
new ECN() {
ECNNumber = 3,
OriginatorID = 1,
Title = "title3",
IsTECN = true,
ExpirationDate = DateTime.Now.AddHours(-12),
ExtensionDate = DateTime.Now.AddDays(10)
ExpirationDate = DateTime.Now.Date.AddHours(12),
ExtensionDate = DateTime.Now.Date.AddDays(10)
},
};

View File

@ -26,4 +26,147 @@ public class TrainingServiceTests {
public void TrainingServiceWithNullDalServiceShouldThrowException() {
Assert.Throws<ArgumentNullException>(() => new TrainingService(_mockLogger.Object, null));
}
[Test]
public void DeleteDocAssignmentWithInvalidIdShouldThrowException() {
_trainingService = new TrainingService(_mockLogger.Object, _mockDalService.Object);
Assert.ThrowsAsync<ArgumentException>(async Task () => await _trainingService.DeleteDocAssignment(-1));
}
[Test]
public void DeleteDocAssignmentWithDbErrorShouldThrowException() {
_mockDalService.Setup(d => d.ExecuteAsync(It.IsAny<string>())).Throws(new Exception());
_trainingService = new TrainingService(_mockLogger.Object, _mockDalService.Object);
Assert.ThrowsAsync<Exception>(async Task () => await _trainingService.DeleteDocAssignment(1));
}
[Test]
public async Task DeleteDocAssignmentShouldExecuteSqlQuery() {
_mockDalService.Setup(d => d.ExecuteAsync(It.IsAny<string>())).Returns(Task.FromResult(3));
_trainingService = new TrainingService(_mockLogger.Object, _mockDalService.Object);
await _trainingService.DeleteDocAssignment(3);
_mockDalService.Verify(d => d.ExecuteAsync(It.IsAny<string>()));
}
[Test]
public void DeleteTrainingAssignmentWithInvalidIdShouldThrowException() {
_trainingService = new TrainingService(_mockLogger.Object, _mockDalService.Object);
Assert.ThrowsAsync<ArgumentException>(async Task () => await _trainingService.DeleteTrainingAssignment(-1));
}
[Test]
public void DeleteTrainingAssignmentWithDbErrorShouldThrowException() {
_mockDalService.Setup(d => d.ExecuteAsync(It.IsAny<string>())).Throws(new Exception());
_trainingService = new TrainingService(_mockLogger.Object, _mockDalService.Object);
Assert.ThrowsAsync<Exception>(async Task () => await _trainingService.DeleteTrainingAssignment(1));
}
[Test]
public async Task DeleteTrainingAssignmentShouldExecuteSqlQuery() {
_mockDalService.Setup(d => d.ExecuteAsync(It.IsAny<string>())).Returns(Task.FromResult(3));
_trainingService = new TrainingService(_mockLogger.Object, _mockDalService.Object);
await _trainingService.DeleteTrainingAssignment(3);
_mockDalService.Verify(d => d.ExecuteAsync(It.IsAny<string>()));
}
[Test]
public void GetTrainingAssignmentIdsForTrainingWithInvalidIdShouldThrowException() {
_trainingService = new TrainingService(_mockLogger.Object, _mockDalService.Object);
Assert.ThrowsAsync<ArgumentException>(async Task () => {
IEnumerable<int> ids = await _trainingService.GetTrainingAssignmentIdsForTraining(-1);
});
}
[Test]
public void GetTrainingAssignmentIdsForTrainingWithDbErrorShouldThrowException() {
_mockDalService.Setup(d => d.QueryAsync<int>(It.IsAny<string>())).Throws(new Exception());
_trainingService = new TrainingService(_mockLogger.Object, _mockDalService.Object);
Assert.ThrowsAsync<Exception>(async Task () => await _trainingService.GetTrainingAssignmentIdsForTraining(1));
}
[Test]
public async Task GetTrainingAssignmentIdsForTrainingShouldReturnExpectedIds() {
IEnumerable<int> expectedIds = new List<int>() { 4, 7, 2 };
_mockDalService.Setup(d => d.QueryAsync<int>(It.IsAny<string>())).Returns(Task.FromResult(expectedIds));
_trainingService = new TrainingService(_mockLogger.Object, _mockDalService.Object);
IEnumerable<int> actualIds = await _trainingService.GetTrainingAssignmentIdsForTraining(1);
Assert.That(actualIds.Count(), Is.EqualTo(expectedIds.Count()));
}
[Test]
public void GetTrainingIdsForEcnWithInvalidIdShouldThrowException() {
_trainingService = new TrainingService(_mockLogger.Object, _mockDalService.Object);
Assert.ThrowsAsync<ArgumentException>(async Task () => {
IEnumerable<int> ids = await _trainingService.GetTrainingIdsForECN(-1);
});
}
[Test]
public void GetTrainingIdsForEcnWithDbErrorShouldThrowException() {
_mockDalService.Setup(d => d.QueryAsync<int>(It.IsAny<string>())).Throws(new Exception());
_trainingService = new TrainingService(_mockLogger.Object, _mockDalService.Object);
Assert.ThrowsAsync<Exception>(async Task () => await _trainingService.GetTrainingIdsForECN(1));
}
[Test]
public async Task GetTrainingIdsForEcnsShouldReturnExpectedIds() {
IEnumerable<int> expectedIds = new List<int>() { 4, 7, 2 };
_mockDalService.Setup(d => d.QueryAsync<int>(It.IsAny<string>())).Returns(Task.FromResult(expectedIds));
_trainingService = new TrainingService(_mockLogger.Object, _mockDalService.Object);
IEnumerable<int> actualIds = await _trainingService.GetTrainingIdsForECN(1);
Assert.That(actualIds.Count(), Is.EqualTo(expectedIds.Count()));
}
[Test]
public void MarkTrainingAsCompleteWithInvalidIdShouldThrowException() {
_trainingService = new TrainingService(_mockLogger.Object, _mockDalService.Object);
Assert.ThrowsAsync<ArgumentException>(async Task() => await _trainingService.MarkTrainingAsComplete(-1));
}
[Test]
public void MarkTrainingCompleteWithDbErrorShouldThrowException() {
_mockDalService.Setup(d => d.ExecuteAsync(It.IsAny<string>())).Throws(new Exception());
_trainingService = new TrainingService(_mockLogger.Object, _mockDalService.Object);
Assert.ThrowsAsync<Exception>(async Task () => await _trainingService.MarkTrainingAsComplete(1));
}
[Test]
public async Task MarkTrainingCompleteShouldExecuteSql() {
_mockDalService.Setup(d => d.ExecuteAsync(It.IsAny<string>())).Returns(Task.FromResult(1));
_trainingService = new TrainingService(_mockLogger.Object, _mockDalService.Object);
await _trainingService.MarkTrainingAsComplete(1);
_mockDalService.Verify(d => d.ExecuteAsync(It.IsAny<string>()));
}
}

View File

@ -272,13 +272,6 @@ internal class UserServiceTests {
Assert.ThrowsAsync<ArgumentException>(async Task () => await _userService.RemoveDelegatedUserSubRoles(0, 2));
}
[Test]
public async Task RemoveDelegateUserSubRolesWithInvalidDelegateIdShouldThrowException() {
_userService = new UserService(MOCK_LOGGER, _mockDalService.Object);
Assert.ThrowsAsync<ArgumentException>(async Task () => await _userService.RemoveDelegatedUserSubRoles(2, 0));
}
[Test]
public async Task RemoveDelegatedUserSubRolesWithValidParamsShouldReturnTrue() {
IEnumerable<int> roleIds = new List<int>() {1, 2};
@ -323,13 +316,6 @@ internal class UserServiceTests {
Assert.ThrowsAsync<ArgumentException>(async Task () => await _userService.RemoveDelegatedApprovalsForUser(0, 2));
}
[Test]
public async Task RemoveDelegatedApprovalsForUserWithInvalidDelegateIdShouldThrowException() {
_userService = new UserService(MOCK_LOGGER, _mockDalService.Object);
Assert.ThrowsAsync<ArgumentException>(async Task () => await _userService.RemoveDelegatedApprovalsForUser(2, 0));
}
[Test]
public async Task RemoveDelegatedApprovalsForUserWithValidUserIdShouldReturnTrue() {
IEnumerable<int> roleIds = new List<int>() { 1, 2 };