diff --git a/EnvelopeGenerator.Finalizer.Win/EnvelopeGenerator.Finalizer.Win.csproj b/EnvelopeGenerator.Finalizer.Win/EnvelopeGenerator.Finalizer.Win.csproj
new file mode 100644
index 00000000..cf43df87
--- /dev/null
+++ b/EnvelopeGenerator.Finalizer.Win/EnvelopeGenerator.Finalizer.Win.csproj
@@ -0,0 +1,44 @@
+
+
+
+ net8.0-windows
+ enable
+ enable
+ dotnet-EnvelopeGenerator.Finalizer.Win-6d5cc618-4159-4ff2-b600-8a15fbfa8099
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+
diff --git a/EnvelopeGenerator.Finalizer.Win/Extensions.cs b/EnvelopeGenerator.Finalizer.Win/Extensions.cs
new file mode 100644
index 00000000..5c0af349
--- /dev/null
+++ b/EnvelopeGenerator.Finalizer.Win/Extensions.cs
@@ -0,0 +1,35 @@
+using EnvelopeGenerator.Finalizer.Job;
+using Quartz;
+
+namespace EnvelopeGenerator.Finalizer;
+
+public static class Extensions
+{
+ public static IServiceCollectionQuartzConfigurator ScheduleJobDefault(this IServiceCollectionQuartzConfigurator q,
+ string croneEpression)
+ where TJob : IJob
+ {
+ var name = $"{typeof(TJob).FullName}";
+ var jobKey = new JobKey(name);
+
+ return q.ScheduleJob(trigger => trigger
+ .WithIdentity(name + "-trigger")
+ .WithCronSchedule(croneEpression),
+ job => job.WithIdentity(jobKey)
+ );
+ }
+
+ public static IServiceCollectionQuartzConfigurator ScheduleJobDefault(this IServiceCollectionQuartzConfigurator q,
+ IConfiguration configuration)
+ where TJob : IJob
+ {
+ var expression = configuration[$"{typeof(TJob).Name}:CronExpression"];
+ if (string.IsNullOrWhiteSpace(expression))
+ throw new InvalidOperationException(
+ "Cron expression for the Worker job is not configured. " +
+ "Please provide a valid cron schedule in the configuration under " +
+ $"'{typeof(TJob).FullName}:CronExpression'.");
+
+ return q.ScheduleJobDefault(expression);
+ }
+}
\ No newline at end of file
diff --git a/EnvelopeGenerator.Finalizer.Win/Job/CreateReportJob.cs b/EnvelopeGenerator.Finalizer.Win/Job/CreateReportJob.cs
new file mode 100644
index 00000000..69328a7c
--- /dev/null
+++ b/EnvelopeGenerator.Finalizer.Win/Job/CreateReportJob.cs
@@ -0,0 +1,28 @@
+using EnvelopeGenerator.Application.Common.Configurations;
+using MediatR;
+using Microsoft.Extensions.Options;
+using Quartz;
+
+namespace EnvelopeGenerator.Finalizer.Job
+{
+ public class CreateReportJob : IJob
+ {
+ private readonly ILogger _logger;
+
+ private readonly IMediator _mediator;
+
+ private readonly PDFBurnerParams _options;
+
+ public CreateReportJob(ILogger logger, IMediator mediator, IOptions options)
+ {
+ _logger = logger;
+ _mediator = mediator;
+ _options = options.Value;
+ }
+
+ public Task Execute(IJobExecutionContext context)
+ {
+ return Task.CompletedTask;
+ }
+ }
+}
\ No newline at end of file
diff --git a/EnvelopeGenerator.Finalizer.Win/Program.cs b/EnvelopeGenerator.Finalizer.Win/Program.cs
new file mode 100644
index 00000000..e88b0199
--- /dev/null
+++ b/EnvelopeGenerator.Finalizer.Win/Program.cs
@@ -0,0 +1,128 @@
+using EnvelopeGenerator.DependencyInjection;
+using EnvelopeGenerator.Finalizer;
+using EnvelopeGenerator.Finalizer.Job;
+using EnvelopeGenerator.Infrastructure;
+using Microsoft.EntityFrameworkCore;
+using Quartz;
+using Quartz.AspNetCore;
+using Quartzmon;
+using Serilog;
+
+// Load Serilog from appsettings.json
+Log.Logger = new LoggerConfiguration()
+ .ReadFrom.Configuration(new ConfigurationBuilder()
+ .AddJsonFile("appsettings.Logging.json", optional: false, reloadOnChange: true)
+ .Build())
+ .CreateLogger();
+
+try
+{
+ Log.Information("Application is starting...");
+
+ var builder = WebApplication.CreateBuilder(args);
+
+ #region Logging
+ builder.Logging.ClearProviders();
+ builder.Logging.AddSerilog();
+ #endregion
+
+ #region Configuration
+ var config = builder.Configuration;
+ Directory
+ .GetFiles(builder.Environment.ContentRootPath, "appsettings.*.json", SearchOption.TopDirectoryOnly)
+ .Where(file => Path.GetFileName(file) != $"appsettings.Development.json")
+ .Where(file => Path.GetFileName(file) != $"appsettings.migration.json")
+ .ToList()
+ .ForEach(file => config.AddJsonFile(file, true, true));
+ #endregion
+
+ #region Web API Services
+ builder.Services.AddControllers();
+ builder.Services.AddEndpointsApiExplorer();
+ builder.Services.AddSwaggerGen();
+ #endregion
+
+ #region Quartz
+ builder.Services.AddQuartz(q =>
+ {
+ q.ScheduleJobDefault(config);
+ });
+
+ builder.Services.AddQuartzServer(options =>
+ {
+ options.WaitForJobsToComplete = true;
+ });
+
+ builder.Services.AddQuartzmon();
+
+ builder.Services.AddSingleton(provider =>
+ provider.GetRequiredService().GetScheduler().Result
+ );
+ #endregion
+
+ #region Add DB Context, EG Inf. and Services
+ var cnnStrName = "Default";
+ var connStr = config.GetConnectionString(cnnStrName)
+ ?? throw new InvalidOperationException($"Connection string '{cnnStrName}' is missing in the application configuration.");
+
+ builder.Services.AddEnvelopeGenerator(egOptions => egOptions
+ .AddLocalization()
+ .AddDistributedSqlServerCache(options =>
+ {
+ options.ConnectionString = connStr;
+ options.SchemaName = "dbo";
+ options.TableName = "TBDD_CACHE";
+ })
+ .AddInfrastructure(opt =>
+ {
+ opt.AddDbTriggerParams(config);
+ opt.AddDbContext((provider, options) =>
+ {
+ var logger = provider.GetRequiredService>();
+ var useInMemoryDb = config.GetValue("UseInMemoryDb");
+ var dbCtxOpt = useInMemoryDb ? options.UseInMemoryDatabase("EGInMemoryDb") : options.UseSqlServer(connStr);
+ dbCtxOpt.LogTo(log => logger.LogInformation("{log}", log), LogLevel.Trace)
+ .EnableSensitiveDataLogging()
+ .EnableDetailedErrors();
+ });
+ })
+ .AddServices(config, true)
+ );
+ #endregion Add DB Context, EG Inf. and Services
+
+ var app = builder.Build();
+
+ #region Web API Middleware
+ if (app.Environment.IsDevelopment())
+ {
+ app.UseSwagger();
+ app.UseSwaggerUI();
+ }
+
+ app.UseHttpsRedirection();
+
+ app.UseRouting();
+
+ app.UseAuthorization();
+
+ app.UseQuartzmon(new QuartzmonOptions()
+ {
+ Scheduler = app.Services.GetRequiredService(),
+ VirtualPathRoot = "/quartz"
+ });
+
+ app.MapControllers();
+ #endregion
+
+ app.Run();
+
+ Log.Information("The worker was stopped.");
+}
+catch (Exception ex)
+{
+ Log.Fatal(ex, "Worker could not be started!");
+}
+finally
+{
+ Log.CloseAndFlush();
+}
\ No newline at end of file
diff --git a/EnvelopeGenerator.Finalizer.Win/Properties/launchSettings.json b/EnvelopeGenerator.Finalizer.Win/Properties/launchSettings.json
new file mode 100644
index 00000000..2e144339
--- /dev/null
+++ b/EnvelopeGenerator.Finalizer.Win/Properties/launchSettings.json
@@ -0,0 +1,41 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:17119",
+ "sslPort": 44321
+ }
+ },
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": false,
+ "launchUrl": "swagger",
+ "applicationUrl": "http://localhost:5010",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "launchUrl": "quartz",
+ "applicationUrl": "https://localhost:7141;http://localhost:5010",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": false,
+ "launchUrl": "swagger",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/EnvelopeGenerator.Finalizer.Win/appsettings.Database.json b/EnvelopeGenerator.Finalizer.Win/appsettings.Database.json
new file mode 100644
index 00000000..1c7059a7
--- /dev/null
+++ b/EnvelopeGenerator.Finalizer.Win/appsettings.Database.json
@@ -0,0 +1,22 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "UseDbMigration": false,
+ "ConnectionStrings": {
+ "Default": "Server=SDD-VMP04-SQL17\\DD_DEVELOP01;Database=DD_ECM;User Id=sa;Password=dd;Encrypt=false;TrustServerCertificate=True;",
+ "DbMigrationTest": "Server=SDD-VMP04-SQL17\\DD_DEVELOP01;Database=DD_ECM_DATA_MIGR_TEST;User Id=sa;Password=dd;Encrypt=false;TrustServerCertificate=True;"
+ },
+ "DbTriggerParams": {
+ "Envelope": [ "TBSIG_ENVELOPE_AFT_INS" ],
+ "History": [ "TBSIG_ENVELOPE_HISTORY_AFT_INS" ],
+ "EmailOut": [ "TBEMLP_EMAIL_OUT_AFT_INS", "TBEMLP_EMAIL_OUT_AFT_UPD" ],
+ "EnvelopeReceiverReadOnly": [ "TBSIG_ENVELOPE_RECEIVER_READ_ONLY_UPD" ],
+ "Receiver": [],
+ "EmailTemplate": [ "TBSIG_EMAIL_TEMPLATE_AFT_UPD" ]
+ },
+ "UseInMemoryDb": false
+}
\ No newline at end of file
diff --git a/EnvelopeGenerator.Finalizer.Win/appsettings.Development.json b/EnvelopeGenerator.Finalizer.Win/appsettings.Development.json
new file mode 100644
index 00000000..7589f277
--- /dev/null
+++ b/EnvelopeGenerator.Finalizer.Win/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "Debug": true
+}
\ No newline at end of file
diff --git a/EnvelopeGenerator.Finalizer.Win/appsettings.Job.json b/EnvelopeGenerator.Finalizer.Win/appsettings.Job.json
new file mode 100644
index 00000000..45e1fd34
--- /dev/null
+++ b/EnvelopeGenerator.Finalizer.Win/appsettings.Job.json
@@ -0,0 +1,8 @@
+{
+ "FinishEnvelopeJob": {
+ "CronExpression": "* * * * * ?"
+ },
+ "EnvelopeTaskApiJob": {
+ "CronExpression": "* * * * * ?"
+ }
+}
\ No newline at end of file
diff --git a/EnvelopeGenerator.Finalizer.Win/appsettings.Logging.json b/EnvelopeGenerator.Finalizer.Win/appsettings.Logging.json
new file mode 100644
index 00000000..2909cf07
--- /dev/null
+++ b/EnvelopeGenerator.Finalizer.Win/appsettings.Logging.json
@@ -0,0 +1,81 @@
+{
+ "Serilog": {
+ "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
+ "MinimumLevel": {
+ "Default": "Verbose",
+ "Override": {
+ "Microsoft": "Warning",
+ "System": "Warning"
+ }
+ },
+ "WriteTo": [
+ {
+ "Name": "Console",
+ "Args": {
+ "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "File",
+ "Args": {
+ "path": "E:/LogFiles/Digital Data/signFlow.Finalizer/log.Verbose-.txt",
+ "rollingInterval": "Day",
+ "restrictedToMinimumLevel": "Verbose",
+ "retainedFileCountLimit": 30,
+ "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "File",
+ "Args": {
+ "path": "E:/LogFiles/Digital Data/signFlow.Finalizer/log.Debug-.txt",
+ "rollingInterval": "Day",
+ "restrictedToMinimumLevel": "Debug",
+ "retainedFileCountLimit": 30,
+ "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "File",
+ "Args": {
+ "path": "E:/LogFiles/Digital Data/signFlow.Finalizer/log.Info-.txt",
+ "rollingInterval": "Day",
+ "restrictedToMinimumLevel": "Information",
+ "retainedFileCountLimit": 30,
+ "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "File",
+ "Args": {
+ "path": "E:/LogFiles/Digital Data/signFlow.Finalizer/log.Warning-.txt",
+ "rollingInterval": "Day",
+ "restrictedToMinimumLevel": "Warning",
+ "retainedFileCountLimit": 30,
+ "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "File",
+ "Args": {
+ "path": "E:/LogFiles/Digital Data/signFlow.Finalizer/log.Error-.txt",
+ "rollingInterval": "Day",
+ "restrictedToMinimumLevel": "Error",
+ "retainedFileCountLimit": 30,
+ "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "File",
+ "Args": {
+ "path": "E:/LogFiles/Digital Data/signFlow.Finalizer/log.Fatal-.txt",
+ "rollingInterval": "Day",
+ "restrictedToMinimumLevel": "Fatal",
+ "retainedFileCountLimit": 30,
+ "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
+ }
+ }
+ ],
+ "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
+ }
+}
\ No newline at end of file
diff --git a/EnvelopeGenerator.Finalizer.Win/appsettings.PdfBurner.json b/EnvelopeGenerator.Finalizer.Win/appsettings.PdfBurner.json
new file mode 100644
index 00000000..3f0309cb
--- /dev/null
+++ b/EnvelopeGenerator.Finalizer.Win/appsettings.PdfBurner.json
@@ -0,0 +1,14 @@
+{
+ "IgnoredLabels": {
+ "Label": [
+ "Date",
+ "Datum",
+ "ZIP",
+ "PLZ",
+ "Place",
+ "Ort",
+ "Position",
+ "Stellung"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/EnvelopeGenerator.Finalizer.Win/appsettings.json b/EnvelopeGenerator.Finalizer.Win/appsettings.json
new file mode 100644
index 00000000..68e67add
--- /dev/null
+++ b/EnvelopeGenerator.Finalizer.Win/appsettings.json
@@ -0,0 +1,3 @@
+{
+ "GdPictureLicenseKey": "kG1Qf9PwmqgR8aDmIW2zI_ebj48RzqAJegRxcystEmkbTGQqfkNBdFOXIb6C_A00Ra8zZkrHdfjqzOPXK7kgkF2YDhvrqKfqh4WDug2vOt0qO31IommzkANSuLjZ4zmraoubyEVd25rE3veQ2h_j7tGIoH_LyIHmy24GaXsxdG0yCzIBMdiLbMMMDwcPY-809KeZ83Grv76OVhFvcbBWyYc251vou1N-kGg5_ZlHDgfWoY85gTLRxafjD3KS_i9ARW4BMiy36y8n7UP2jN8kGRnW_04ubpFtfjJqvtsrP_J9D0x7bqV8xtVtT5JI6dpKsVTiMgDCrIcoFSo5gCC1fw9oUopX4TDCkBQttO4-WHBlOeq9dG5Yb0otonVmJKaQA2tP6sMR-lZDs3ql_WI9t91yPWgpssrJUxSHDd27_LMTH_owJIqkF3NOJd9mYQuAv22oNKFYbH8e41pVKb8cT33Y9CgcQ_sy6YDA5PTuIRi67mjKge_nD9rd0IN213Ir9M_EFWqg9e4haWzIdHXQUo0md70kVhPX4UIH_BKJnxEEnFfoFRNMh77bB0N4jkcBEHPl-ghOERv8dOztf4vCnNpzzWvcLD2cqWIm6THy8XGGq9h4hp8aEreRleSMwv9QQAC7mjLwhQ1rBYkpUHlpTjhTLnMwHknl6HH0Z6zzmsgkRKVyfquv94Pd7QbQfZrRka0ss_48pf9p8hAywEn81Q=="
+}
\ No newline at end of file
diff --git a/EnvelopeGenerator.sln b/EnvelopeGenerator.sln
index 5f7e6228..de6117b4 100644
--- a/EnvelopeGenerator.sln
+++ b/EnvelopeGenerator.sln
@@ -41,6 +41,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnvelopeGenerator.Dependenc
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnvelopeGenerator.Finalizer", "EnvelopeGenerator.Finalizer\EnvelopeGenerator.Finalizer.csproj", "{C4970E6C-DB2E-48C5-B3C5-2AF589405ED9}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnvelopeGenerator.Finalizer.Win", "EnvelopeGenerator.Finalizer.Win\EnvelopeGenerator.Finalizer.Win.csproj", "{F4844CA5-8747-F32F-E938-45859A2AA422}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -103,6 +105,10 @@ Global
{C4970E6C-DB2E-48C5-B3C5-2AF589405ED9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C4970E6C-DB2E-48C5-B3C5-2AF589405ED9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C4970E6C-DB2E-48C5-B3C5-2AF589405ED9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F4844CA5-8747-F32F-E938-45859A2AA422}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F4844CA5-8747-F32F-E938-45859A2AA422}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F4844CA5-8747-F32F-E938-45859A2AA422}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F4844CA5-8747-F32F-E938-45859A2AA422}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -125,6 +131,7 @@ Global
{211619F5-AE25-4BA5-A552-BACAFE0632D3} = {9943209E-1744-4944-B1BA-4F87FC1A0EEB}
{B97DE7DD-3190-4A84-85E9-E57AD735BE61} = {E3C758DC-914D-4B7E-8457-0813F1FDB0CB}
{C4970E6C-DB2E-48C5-B3C5-2AF589405ED9} = {E3C758DC-914D-4B7E-8457-0813F1FDB0CB}
+ {F4844CA5-8747-F32F-E938-45859A2AA422} = {E3C758DC-914D-4B7E-8457-0813F1FDB0CB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {73E60370-756D-45AD-A19A-C40A02DACCC7}