Created Windows Service
This commit is contained in:
parent
35690df362
commit
794b616293
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
|||||||
bin
|
bin
|
||||||
obj
|
obj
|
||||||
TestResults
|
TestResults
|
||||||
|
Properties
|
@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Worker">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
@ -8,6 +8,9 @@
|
|||||||
<ServerGarbageCollection>true</ServerGarbageCollection>
|
<ServerGarbageCollection>true</ServerGarbageCollection>
|
||||||
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
||||||
<Configurations>Debug;Release;Staging</Configurations>
|
<Configurations>Debug;Release;Staging</Configurations>
|
||||||
|
<OutputType>exe</OutputType>
|
||||||
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
@ -26,12 +29,15 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Autofac.Extras.Quartz" Version="10.0.0" />
|
||||||
<PackageReference Include="Dapper" Version="2.1.28" />
|
<PackageReference Include="Dapper" Version="2.1.28" />
|
||||||
<PackageReference Include="Dapper.Contrib" Version="2.0.78" />
|
<PackageReference Include="Dapper.Contrib" Version="2.0.78" />
|
||||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.0" />
|
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.0" />
|
||||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.2" />
|
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.2" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
||||||
<PackageReference Include="NLog" Version="5.2.8" />
|
<PackageReference Include="NLog" Version="5.2.8" />
|
||||||
<PackageReference Include="NLog.Extensions.Logging" Version="5.3.8" />
|
<PackageReference Include="NLog.Extensions.Logging" Version="5.3.8" />
|
||||||
<PackageReference Include="Quartz" Version="3.8.1" />
|
<PackageReference Include="Quartz" Version="3.8.1" />
|
||||||
|
@ -4,5 +4,6 @@
|
|||||||
<Controller_SelectedScaffolderID>ApiControllerEmptyScaffolder</Controller_SelectedScaffolderID>
|
<Controller_SelectedScaffolderID>ApiControllerEmptyScaffolder</Controller_SelectedScaffolderID>
|
||||||
<Controller_SelectedScaffolderCategoryPath>root/Common/Api</Controller_SelectedScaffolderCategoryPath>
|
<Controller_SelectedScaffolderCategoryPath>root/Common/Api</Controller_SelectedScaffolderCategoryPath>
|
||||||
<NameOfLastUsedPublishProfile>C:\Users\tuckerc\FabApprovalWorkerService\FabApprovalWorkerService\Properties\PublishProfiles\Staging.pubxml</NameOfLastUsedPublishProfile>
|
<NameOfLastUsedPublishProfile>C:\Users\tuckerc\FabApprovalWorkerService\FabApprovalWorkerService\Properties\PublishProfiles\Staging.pubxml</NameOfLastUsedPublishProfile>
|
||||||
|
<_LastSelectedProfileId>C:\Users\tuckerc\FabApprovalWorkerService\FabApprovalWorkerService\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
@ -1,10 +1,14 @@
|
|||||||
namespace FabApprovalWorkerService.Models;
|
using Dapper.Contrib.Extensions;
|
||||||
|
|
||||||
|
namespace FabApprovalWorkerService.Models;
|
||||||
|
|
||||||
|
[Table("ECN")]
|
||||||
public class ECN {
|
public class ECN {
|
||||||
|
[Key]
|
||||||
public required int ECNNumber { get; set; }
|
public required int ECNNumber { get; set; }
|
||||||
public bool IsTECN { get; set; } = false;
|
public bool IsTECN { get; set; } = false;
|
||||||
public DateTime ExpirationDate { get; set; }
|
public DateTime ExpirationDate { get; set; }
|
||||||
public DateTime? ExtensionDate { get; set; }
|
public DateTime ExtensionDate { get; set; } = DateTime.MinValue;
|
||||||
public required int OriginatorID { get; set; }
|
public required int OriginatorID { get; set; }
|
||||||
public required string Title { get; set; }
|
public required string Title { get; set; }
|
||||||
}
|
}
|
||||||
|
12
FabApprovalWorkerService/Models/TrainingAssignment.cs
Normal file
12
FabApprovalWorkerService/Models/TrainingAssignment.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
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; }
|
||||||
|
}
|
@ -8,7 +8,7 @@ using Quartz;
|
|||||||
|
|
||||||
using System.Net.Mail;
|
using System.Net.Mail;
|
||||||
|
|
||||||
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
|
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
|
||||||
|
|
||||||
builder.Logging.ClearProviders();
|
builder.Logging.ClearProviders();
|
||||||
builder.Logging.SetMinimumLevel(LogLevel.Trace);
|
builder.Logging.SetMinimumLevel(LogLevel.Trace);
|
||||||
@ -36,11 +36,7 @@ builder.Services.AddQuartz(q => {
|
|||||||
q.AddTrigger(opts => opts
|
q.AddTrigger(opts => opts
|
||||||
.ForJob(pendingOOOStatusJob)
|
.ForJob(pendingOOOStatusJob)
|
||||||
.WithIdentity("Pending OOO status trigger")
|
.WithIdentity("Pending OOO status trigger")
|
||||||
.WithSimpleSchedule(x => x
|
.WithCronSchedule(CronScheduleBuilder.DailyAtHourAndMinute(0, 0))
|
||||||
.WithIntervalInMinutes(10)
|
|
||||||
.RepeatForever()
|
|
||||||
)
|
|
||||||
.StartNow()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
JobKey expiredOOOStatusJob = new JobKey("Expired OOO status job");
|
JobKey expiredOOOStatusJob = new JobKey("Expired OOO status job");
|
||||||
@ -50,6 +46,16 @@ builder.Services.AddQuartz(q => {
|
|||||||
q.AddTrigger(opts => opts
|
q.AddTrigger(opts => opts
|
||||||
.ForJob(expiredOOOStatusJob)
|
.ForJob(expiredOOOStatusJob)
|
||||||
.WithIdentity("Expired OOO status trigger")
|
.WithIdentity("Expired OOO status trigger")
|
||||||
|
.WithCronSchedule(CronScheduleBuilder.DailyAtHourAndMinute(0, 0))
|
||||||
|
);
|
||||||
|
|
||||||
|
JobKey expiringTECNJob = new JobKey("Expiring TECN job");
|
||||||
|
q.AddJob<ExpiringTECNWorker>(opts => opts
|
||||||
|
.WithIdentity(expiringTECNJob)
|
||||||
|
);
|
||||||
|
q.AddTrigger(opts => opts
|
||||||
|
.ForJob(expiringTECNJob)
|
||||||
|
.WithIdentity("Expiring TECN trigger")
|
||||||
.WithSimpleSchedule(x => x
|
.WithSimpleSchedule(x => x
|
||||||
.WithIntervalInMinutes(10)
|
.WithIntervalInMinutes(10)
|
||||||
.RepeatForever()
|
.RepeatForever()
|
||||||
@ -62,6 +68,11 @@ builder.Services.AddQuartzHostedService(opt => {
|
|||||||
opt.WaitForJobsToComplete = true;
|
opt.WaitForJobsToComplete = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
WebApplication app = builder.Build();
|
builder.Services.AddWindowsService(options => {
|
||||||
|
options.ServiceName = "Fab Approval Worker Service";
|
||||||
|
});
|
||||||
|
builder.Services.AddHostedService<WindowsService>();
|
||||||
|
|
||||||
|
IHost app = builder.Build();
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
|
@ -32,13 +32,13 @@ public class ECNService : IECNService {
|
|||||||
queryBuilder.Append($"ExpirationDate between '{yesterday}' ");
|
queryBuilder.Append($"ExpirationDate between '{yesterday}' ");
|
||||||
queryBuilder.Append($"and '{today}'");
|
queryBuilder.Append($"and '{today}'");
|
||||||
|
|
||||||
IEnumerable<ECN> expiredTecns = (await _dalService.QueryAsync<ECN>(queryBuilder.ToString()))
|
IEnumerable<ECN> expiredTecns = (await _dalService.QueryAsync<ECN>(queryBuilder.ToString()));
|
||||||
.Where(e => e.ExtensionDate is null || e.ExtensionDate < DateTime.Now)
|
|
||||||
|
IEnumerable<ECN> expiredTecnsNotExtended = expiredTecns
|
||||||
|
.Where(e => e.ExtensionDate < DateTime.Now)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
_logger.LogInformation($"Found {expiredTecns.Count()} expired TECNs");
|
return expiredTecnsNotExtended;
|
||||||
|
|
||||||
return expiredTecns;
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
StringBuilder errMsgBuilder = new();
|
StringBuilder errMsgBuilder = new();
|
||||||
errMsgBuilder.Append("An exception occurred when attempting to get all TECNs expired in the last day. ");
|
errMsgBuilder.Append("An exception occurred when attempting to get all TECNs expired in the last day. ");
|
||||||
@ -56,18 +56,18 @@ public class ECNService : IECNService {
|
|||||||
string fiveDaysFromToday = DateTime.Now.AddDays(5).ToString("yyyy-MM-dd HH:mm:ss");
|
string fiveDaysFromToday = DateTime.Now.AddDays(5).ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
StringBuilder queryBuilder = new StringBuilder();
|
StringBuilder queryBuilder = new StringBuilder();
|
||||||
queryBuilder.Append("select ECNNumber, IsTECN, ExpirationDate, ExtensionDate, OriginatorID, Title ");
|
queryBuilder.Append("select * from ECN ");
|
||||||
queryBuilder.Append($"from ECN where IsTECN = 1 and ");
|
queryBuilder.Append($"where IsTECN = 1 and ");
|
||||||
queryBuilder.Append($"ExpirationDate between '{today}' ");
|
queryBuilder.Append($"ExpirationDate between '{today}' ");
|
||||||
queryBuilder.Append($"and '{fiveDaysFromToday}'");
|
queryBuilder.Append($"and '{fiveDaysFromToday}';");
|
||||||
|
|
||||||
IEnumerable<ECN> expiringTecns = (await _dalService.QueryAsync<ECN>(queryBuilder.ToString()))
|
IEnumerable<ECN> expiringTecns = (await _dalService.QueryAsync<ECN>(queryBuilder.ToString()));
|
||||||
.Where(e => e.ExtensionDate is null || e.ExtensionDate <= DateTime.Now.AddDays(5))
|
|
||||||
|
IEnumerable<ECN> expiringTecnsNotExtended = expiringTecns
|
||||||
|
.Where(e => e.ExtensionDate <= DateTime.Now.AddDays(5))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
_logger.LogInformation($"Found {expiringTecns.Count()} expiring TECNs");
|
return expiringTecnsNotExtended;
|
||||||
|
|
||||||
return expiringTecns;
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
StringBuilder errMsgBuilder = new();
|
StringBuilder errMsgBuilder = new();
|
||||||
errMsgBuilder.Append("An exception occurred when attempting to get all TECNs expiring in the next five days. ");
|
errMsgBuilder.Append("An exception occurred when attempting to get all TECNs expiring in the next five days. ");
|
||||||
|
102
FabApprovalWorkerService/Services/TrainingService.cs
Normal file
102
FabApprovalWorkerService/Services/TrainingService.cs
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
using FabApprovalWorkerService.Models;
|
||||||
|
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace FabApprovalWorkerService.Services;
|
||||||
|
|
||||||
|
public interface ITrainingService {
|
||||||
|
Task<IEnumerable<int>> GetTrainingIdsForECN(int ecnNumber);
|
||||||
|
Task DeleteTrainingAssignment(int trainingId);
|
||||||
|
Task<IEnumerable<int>> GetTrainingAssignmentIdsForTraining(int trainingId);
|
||||||
|
Task DeleteDocAssignment(int trainingAssignmentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TrainingService : ITrainingService {
|
||||||
|
private ILogger<TrainingService> _logger;
|
||||||
|
private IDalService _dalService;
|
||||||
|
|
||||||
|
public TrainingService(ILogger<TrainingService> logger, IDalService dalService) {
|
||||||
|
_logger = logger ??
|
||||||
|
throw new ArgumentNullException("ILogger not injected");
|
||||||
|
_dalService = dalService ??
|
||||||
|
throw new ArgumentNullException("IDalService not injected");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteDocAssignment(int trainingAssignmentId) {
|
||||||
|
if (trainingAssignmentId <= 0) throw new ArgumentException($"Invalid training assignment id: {trainingAssignmentId}");
|
||||||
|
|
||||||
|
try {
|
||||||
|
_logger.LogInformation($"Attempting to delete training doc assignments for training assignment {trainingAssignmentId}");
|
||||||
|
|
||||||
|
StringBuilder queryBuilder = new();
|
||||||
|
queryBuilder.Append($"update TrainingDocAcks set Deleted = 1, ");
|
||||||
|
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());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
StringBuilder errMsgBuilder = new();
|
||||||
|
errMsgBuilder.Append($"An exception occurred when attempting to delete training doc assignment ");
|
||||||
|
errMsgBuilder.Append($"{trainingAssignmentId}. Exception: {ex.Message}");
|
||||||
|
_logger.LogError(errMsgBuilder.ToString());
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteTrainingAssignment(int trainingId) {
|
||||||
|
if (trainingId <= 0) throw new ArgumentException($"Invalid training id: {trainingId}");
|
||||||
|
|
||||||
|
try {
|
||||||
|
_logger.LogInformation($"Attempting to delete training assignment {trainingId}");
|
||||||
|
|
||||||
|
StringBuilder queryBuilder = new();
|
||||||
|
queryBuilder.Append($"update TrainingAssignments set Deleted = 1, ");
|
||||||
|
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());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
StringBuilder errMsgBuilder = new();
|
||||||
|
errMsgBuilder.Append($"An exception occurred when attempting to delete training assignment ");
|
||||||
|
errMsgBuilder.Append($"{trainingId}. 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}");
|
||||||
|
|
||||||
|
try {
|
||||||
|
_logger.LogInformation($"Attempting to get training assignment ids for training id {trainingId}");
|
||||||
|
|
||||||
|
string sql = $"select ID from TrainingAssignments where TrainingID = {trainingId};";
|
||||||
|
|
||||||
|
return await _dalService.QueryAsync<int>(sql);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
StringBuilder errMsgBuilder = new();
|
||||||
|
errMsgBuilder.Append($"An exception occurred when attempting to get training assignment ids ");
|
||||||
|
errMsgBuilder.Append($"for training id {trainingId}. Exception: {ex.Message}");
|
||||||
|
_logger.LogError(errMsgBuilder.ToString());
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<int>> GetTrainingIdsForECN(int ecnNumber) {
|
||||||
|
if (ecnNumber <= 0) throw new ArgumentException($"Invalid ecnNumber: {ecnNumber}");
|
||||||
|
|
||||||
|
try {
|
||||||
|
_logger.LogInformation($"Attempting to get training ids for ecn {ecnNumber}");
|
||||||
|
|
||||||
|
string sql = $"select TrainingID from Training where ECN = {ecnNumber};";
|
||||||
|
|
||||||
|
return await _dalService.QueryAsync<int>(sql);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
StringBuilder errMsgBuilder = new();
|
||||||
|
errMsgBuilder.Append($"An exception occurred when attempting to get training ids ");
|
||||||
|
errMsgBuilder.Append($"for ECN {ecnNumber}. Exception: {ex.Message}");
|
||||||
|
_logger.LogError(errMsgBuilder.ToString());
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
FabApprovalWorkerService/Services/WindowsService.cs
Normal file
40
FabApprovalWorkerService/Services/WindowsService.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using FabApprovalWorkerService.Models;
|
||||||
|
|
||||||
|
namespace FabApprovalWorkerService.Services;
|
||||||
|
|
||||||
|
public class WindowsService : BackgroundService {
|
||||||
|
private readonly ILogger<WindowsService> _logger;
|
||||||
|
private readonly IMonInWorkerClient _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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
|
||||||
|
_logger.LogInformation("Starting Windows service");
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (!stoppingToken.IsCancellationRequested) {
|
||||||
|
await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
|
||||||
|
|
||||||
|
_monInClient.PostStatus("WindowsService", StatusValue.Ok);
|
||||||
|
}
|
||||||
|
} catch (OperationCanceledException) {
|
||||||
|
_logger.LogError("The Windows service has been stopped");
|
||||||
|
|
||||||
|
_monInClient.PostStatus("WindowsService", StatusValue.Critical);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
_logger.LogError($"An exception occurred when running Windows Service. Exception: {ex.Message}");
|
||||||
|
|
||||||
|
_monInClient.PostStatus("WindowsService", StatusValue.Critical);
|
||||||
|
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,16 @@
|
|||||||
drop table if exists ECN;
|
drop table if exists ECN;
|
||||||
|
|
||||||
create table ECN (
|
create table ECN (
|
||||||
ECNID integer primary key,
|
ECNNumber integer primary key not null,
|
||||||
ECNNumber integer not null,
|
|
||||||
IsTECN integer default 0,
|
IsTECN integer default 0,
|
||||||
ExpirationDate text not null,
|
ExpirationDate text,
|
||||||
ExtensionDate text,
|
ExtensionDate text,
|
||||||
OriginatorID integer not null,
|
OriginatorID integer not null,
|
||||||
Title text not null
|
Title text not null
|
||||||
);
|
);
|
||||||
|
|
||||||
insert into ECN (ECNNumber, IsTECN, ExpirationDate, ExtensionDate, OriginatorID, Title)
|
insert into ECN (ECNNumber, IsTECN, ExpirationDate, ExtensionDate, OriginatorID, Title)
|
||||||
values (1, 0, '2024-03-30 00:00:00', '', 1, 'title1'),
|
values (1, 0, '2024-04-06 00:00:00', null, 1, 'title1'),
|
||||||
(2, 1, '2024-04-01 00:00:00', '', 6, 'title2'),
|
(2, 1, '2024-04-04 00:00:00', null, 6, 'title2'),
|
||||||
(3, 1, '2024-06-01 00:00:00', '', 4, 'title3'),
|
(3, 1, '2024-06-01 00:00:00', null, 4, 'title3'),
|
||||||
(4, 1, '2024-04-01 00:00:00', '2024-06-01 00:00:00', 3, 'title4')
|
(4, 1, '2024-04-03 00:00:00', '2024-06-01 00:00:00', 3, 'title4')
|
@ -1,9 +1,9 @@
|
|||||||
drop table if exists TECNNotificationUsers;
|
drop table if exists TECNNotificationsUsers;
|
||||||
|
|
||||||
create table TECNNotificationUsers (
|
create table TECNNotificationsUsers (
|
||||||
Id integer primary key,
|
Id integer primary key,
|
||||||
UserId integer not null
|
UserId integer not null
|
||||||
);
|
);
|
||||||
|
|
||||||
insert into TECNNotificationUsers (UserId)
|
insert into TECNNotificationsUsers (UserId)
|
||||||
values (1), (2), (3);
|
values (1), (2), (3);
|
@ -43,6 +43,8 @@ public class ExpiringTECNWorker : IJob {
|
|||||||
|
|
||||||
IEnumerable<ECN> expiringTECNs = await _ecnService.GetExpiringTECNs();
|
IEnumerable<ECN> expiringTECNs = await _ecnService.GetExpiringTECNs();
|
||||||
|
|
||||||
|
_logger.LogInformation($"There are {expiringTECNs.Count()} TECNs expiring in the next 5 days");
|
||||||
|
|
||||||
foreach (ECN eCN in expiringTECNs) {
|
foreach (ECN eCN in expiringTECNs) {
|
||||||
string recipientEmail = await _userService.GetUserEmail(eCN.OriginatorID);
|
string recipientEmail = await _userService.GetUserEmail(eCN.OriginatorID);
|
||||||
MailAddress recipientAddress = new MailAddress(recipientEmail);
|
MailAddress recipientAddress = new MailAddress(recipientEmail);
|
||||||
@ -55,9 +57,8 @@ public class ExpiringTECNWorker : IJob {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder bodyBuilder = new();
|
StringBuilder bodyBuilder = new();
|
||||||
bodyBuilder.Append($"Good day, TECN# {eCN.ECNNumber} will be expiring in ");
|
bodyBuilder.Append($"Good day, TECN# {eCN.ECNNumber} will be expire on ");
|
||||||
bodyBuilder.Append($"{(eCN.ExpirationDate - DateTime.Now).Days} ");
|
bodyBuilder.Append($"{eCN.ExpirationDate.ToString("MMMM dd, yyyy")}. ");
|
||||||
bodyBuilder.Append($"on {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='https://mesaapproval.mes.com/ECN/Edit?IssueID={eCN.ECNNumber}'> ");
|
||||||
bodyBuilder.Append("here </a>");
|
bodyBuilder.Append("here </a>");
|
||||||
|
|
||||||
|
@ -112,6 +112,9 @@ internal class SmtpServiceTests {
|
|||||||
|
|
||||||
Assert.True(await _smtpService.SendEmail(ADDRESS_LIST, ADDRESS_LIST, "subject", "body"));
|
Assert.True(await _smtpService.SendEmail(ADDRESS_LIST, ADDRESS_LIST, "subject", "body"));
|
||||||
|
|
||||||
|
string? env = Environment.GetEnvironmentVariable("FabApprovalEnvironmentName");
|
||||||
|
|
||||||
|
if (env is not null && !env.ToLower().Equals("development"))
|
||||||
_mockSmtpClient.Verify(s => s.Send(It.IsAny<MailMessage>()));
|
_mockSmtpClient.Verify(s => s.Send(It.IsAny<MailMessage>()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
29
FabApprovalWorkerServiceTests/TrainingServiceTests.cs
Normal file
29
FabApprovalWorkerServiceTests/TrainingServiceTests.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using FabApprovalWorkerService.Services;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
using Moq;
|
||||||
|
|
||||||
|
namespace FabApprovalWorkerServiceTests;
|
||||||
|
public class TrainingServiceTests {
|
||||||
|
private Mock<ILogger<TrainingService>> _mockLogger;
|
||||||
|
private Mock<IDalService> _mockDalService;
|
||||||
|
|
||||||
|
private TrainingService _trainingService;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup() {
|
||||||
|
_mockLogger = new Mock<ILogger<TrainingService>>();
|
||||||
|
_mockDalService = new Mock<IDalService>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TrainingServiceWithNullLoggerShouldThrowException() {
|
||||||
|
Assert.Throws<ArgumentNullException>(() => new TrainingService(null, _mockDalService.Object));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TrainingServiceWithNullDalServiceShouldThrowException() {
|
||||||
|
Assert.Throws<ArgumentNullException>(() => new TrainingService(_mockLogger.Object, null));
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user