Compare commits
82 Commits
feat/annot
...
36b03da084
| Author | SHA1 | Date | |
|---|---|---|---|
| 36b03da084 | |||
| defa53fa26 | |||
| 6134b58a4c | |||
| 5299016b43 | |||
| 55c20e83d8 | |||
| f1a140faa7 | |||
| b20d25e5b9 | |||
| e21eb2c0d6 | |||
| d237b4ab95 | |||
| dff99b163d | |||
| 70fbf31b14 | |||
| 339e0e81cd | |||
| a386ad72bb | |||
| 02c5f286ec | |||
| 5fa358ca79 | |||
| 7233d2ce98 | |||
| 5784cc7a97 | |||
| f31f680f91 | |||
| e7c2d46ef0 | |||
| 85d70c1db4 | |||
| fb340fb08a | |||
| 7d3959ae51 | |||
| 9d4890b10d | |||
| b64f4d71f5 | |||
| b7d146ddb5 | |||
| 6a5c9a3489 | |||
|
|
15f6ee7be0 | ||
|
|
1051c5356f | ||
|
|
7b13350fbf | ||
|
|
2bada327d8 | ||
|
|
a47729ebca | ||
|
|
fcfed963b7 | ||
|
|
b2ace61cd4 | ||
|
|
77cdc83a4e | ||
|
|
a611df4914 | ||
|
|
1341f69ab1 | ||
|
|
0480513288 | ||
|
|
9dbd1b16b5 | ||
|
|
c649c93921 | ||
|
|
1843119b1b | ||
|
|
bc4371cb99 | ||
|
|
05130d6163 | ||
| 567b9c9565 | |||
| b798181f91 | |||
| 7e8fc25ec9 | |||
| db76162697 | |||
| 2b4573ea73 | |||
| 4a043ed247 | |||
| a62a035ec6 | |||
| 1713a65014 | |||
| 695d7c83e0 | |||
| 428f71863d | |||
| cce2f8f90e | |||
|
|
86c9fdfcd7 | ||
|
|
89ec887510 | ||
|
|
7d5b988842 | ||
|
|
3c456562cc | ||
|
|
4d6b01030c | ||
|
|
75e7e9925b | ||
|
|
0a175b9e9d | ||
|
|
f611e74de1 | ||
|
|
08ca116628 | ||
|
|
4997f7d75c | ||
| b5cd42b6fa | |||
| 187f4a42fc | |||
| 23d4b2f31e | |||
| 8e71e5b4bb | |||
| b693615561 | |||
| 36dc9266bc | |||
| 9aabe270b4 | |||
| b303b7be06 | |||
| 02937360ea | |||
| c2735b92e0 | |||
| 568f43186c | |||
| 3bc5439b5a | |||
| 22b494a262 | |||
| 209785dda5 | |||
| 44ea893f05 | |||
| b4aa7984aa | |||
| 7c5a505ad1 | |||
| bd6d57e1e8 | |||
| 8403ce2c6a |
@@ -0,0 +1,12 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Configurations;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class GdPictureParams
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string License { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using EnvelopeGenerator.Application.Common.Interfaces.Model;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Drawing;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Configurations;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class PDFBurnerParams : ITextStyle
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IEnumerable<string> IgnoredLabels { get; set; } = new List<string>
|
||||
{
|
||||
"Date", "Datum", "ZIP", "PLZ", "Place", "Ort", "Position", "Stellung"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
|
||||
public double TopMargin { get; set; } = 0.1;
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public double YOffset { get; set; } = -0.3;
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string FontName { get; set; } = "Arial";
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int FontSize { get; set; } = 8;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>")]
|
||||
public FontStyle FontStyle { get; set; } = FontStyle.Italic;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Dictionary<string, int> IndexOfAnnot { get; init; } = new()
|
||||
{
|
||||
{ string.Empty, 0 },
|
||||
{ "seal", 0 },
|
||||
{ "position", 1 },
|
||||
{ "city", 2 },
|
||||
{ "date", 3 }
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int DefaultIndexOfAnnot { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public int GetAnnotationIndex(string name) => IndexOfAnnot.TryGetValue(name, out var value) ? value : DefaultIndexOfAnnot;
|
||||
}
|
||||
@@ -82,7 +82,7 @@ public record EnvelopeDto
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool UseAccessCode { get; set; } = true;
|
||||
public bool? UseAccessCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
|
||||
@@ -36,6 +36,7 @@ public class MappingProfile : Profile
|
||||
CreateMap<Domain.Entities.Receiver, ReceiverDto>();
|
||||
CreateMap<Domain.Entities.EnvelopeReceiverReadOnly, EnvelopeReceiverReadOnlyDto>();
|
||||
CreateMap<ElementAnnotation, AnnotationDto>();
|
||||
CreateMap<ThirdPartyModule, ThirdPartyModuleDto>();
|
||||
|
||||
// DTO to Entity mappings
|
||||
CreateMap<ConfigDto, Config>();
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
using EnvelopeGenerator.Application.Exceptions;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class Annotation
|
||||
{
|
||||
private string? _id;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int EnvelopeId { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int ReceiverId { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int Index { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string EgName { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool HasStructuredID { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool IsLabel
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(EgName))
|
||||
return false;
|
||||
|
||||
var parts = EgName.Split('_');
|
||||
return parts.Length > 1 && parts[1] == "label";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? Id
|
||||
{
|
||||
get => _id;
|
||||
set
|
||||
{
|
||||
_id = value;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
throw new BurnAnnotationException("The identifier of annotation is null or empty.");
|
||||
|
||||
var parts = value.Split('#');
|
||||
|
||||
if (parts.Length != 4)
|
||||
return;
|
||||
// throw new BurnAnnotationException($"The identifier of annotation has more or less than 4 sub-part. Id: {_id}");
|
||||
|
||||
if (!int.TryParse(parts[0], out int envelopeId))
|
||||
throw new BurnAnnotationException($"The envelope ID of annotation is not integer. Id: {_id}");
|
||||
EnvelopeId = envelopeId;
|
||||
|
||||
if (!int.TryParse(parts[1], out int receiverId))
|
||||
throw new BurnAnnotationException($"The receiver ID of annotation is not integer. Id: {_id}");
|
||||
ReceiverId = receiverId;
|
||||
|
||||
if (!int.TryParse(parts[2], out int index))
|
||||
throw new BurnAnnotationException($"The index of annotation is not integer. Id: {_id}");
|
||||
Index = index;
|
||||
|
||||
EgName = parts[3];
|
||||
HasStructuredID = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<double>? Bbox { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool IsSignature { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? ImageAttachmentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Lines? Lines { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int PageIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? StrokeColor { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="Binary"></param>
|
||||
/// <param name="ContentType"></param>
|
||||
public record Attachment(string Binary, string ContentType);
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="Name"></param>
|
||||
/// <param name="Value"></param>
|
||||
public record FormFieldValue(string Name, string? Value = null);
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="Lines"></param>
|
||||
/// <param name="StrokeColor"></param>
|
||||
public record Ink(Lines Lines, string? StrokeColor = null);
|
||||
@@ -0,0 +1,50 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class InstantData
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<Annotation>? Annotations { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IEnumerable<List<Annotation>>? AnnotationsByReceiver
|
||||
{
|
||||
get
|
||||
{
|
||||
return Annotations?
|
||||
.Where(a => a.HasStructuredID)
|
||||
.GroupBy(a => a.ReceiverId)
|
||||
.Select(g => g.ToList());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IEnumerable<List<Annotation>>? UnstructuredAnnotations
|
||||
{
|
||||
get
|
||||
{
|
||||
return Annotations?
|
||||
.Where(a => !a.HasStructuredID)
|
||||
.GroupBy(a => a.ReceiverId)
|
||||
.Select(g => g.ToList());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Dictionary<string, Attachment>? Attachments { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<FormFieldValue>? FormFieldValues { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="Points"></param>
|
||||
public record Lines(List<List<List<float>>> Points);
|
||||
@@ -0,0 +1,57 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record ThirdPartyModuleDto
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool Active { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Name { get; init; } = default!;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? Description { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string License { get; init; } = default!;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Version { get; init; } = default!;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? AddedWho { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public DateTime? AddedWhen { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? ChangedWho { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public DateTime? ChangedWhen { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
using EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using GdPicture14;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using SixLabors.ImageSharp;
|
||||
using System.Drawing;
|
||||
using EnvelopeGenerator.Application.Common.Extensions;
|
||||
using EnvelopeGenerator.Application.Common.Interfaces.Model;
|
||||
using EnvelopeGenerator.Application.Common.Configurations;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Extensions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class GdPictureExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="page"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="textStyle"></param>
|
||||
public static void AddFormFieldValue(this AnnotationManager manager, double x, double y, double width, double height, int page, string value, ITextStyle textStyle)
|
||||
{
|
||||
manager.SelectPage(page);
|
||||
|
||||
// Add the text annotation
|
||||
var ant = manager.AddTextAnnot((float)x, (float)y, (float)width, (float)height, value);
|
||||
|
||||
// Set the font properties
|
||||
ant.FontName = textStyle.FontName;
|
||||
ant.FontSize = textStyle.FontSize;
|
||||
ant.FontStyle = textStyle.FontStyle;
|
||||
|
||||
manager.SaveAnnotationsToPage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="pAnnotation"></param>
|
||||
/// <param name="formFieldValue"></param>
|
||||
/// <param name="options"></param>
|
||||
public static void AddFormFieldValue(this AnnotationManager manager, Annotation pAnnotation, FormFieldValue formFieldValue, PDFBurnerParams options)
|
||||
{
|
||||
var ffIndex = options.GetAnnotationIndex(pAnnotation.EgName);
|
||||
|
||||
// Convert pixels to Inches
|
||||
var oBounds = pAnnotation.Bbox?.Select(points => points.ToInches()).ToList();
|
||||
|
||||
if (oBounds is null || oBounds.Count < 4)
|
||||
return;
|
||||
|
||||
double oX = oBounds[0];
|
||||
double oY = oBounds[1] + options.YOffset * ffIndex + options.TopMargin;
|
||||
double oWidth = oBounds[2];
|
||||
double oHeight = oBounds[3];
|
||||
|
||||
manager.SelectPage(pAnnotation.PageIndex + 1);
|
||||
|
||||
// Add the text annotation
|
||||
var ant = manager.AddTextAnnot((float)oX, (float)oY, (float)oWidth, (float)oHeight, formFieldValue.Value);
|
||||
|
||||
// Set the font properties
|
||||
ant.FontName = options.FontName;
|
||||
ant.FontSize = options.FontSize;
|
||||
ant.FontStyle = options.FontStyle;
|
||||
|
||||
manager.SaveAnnotationsToPage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="page"></param>
|
||||
/// <param name="base64"></param>
|
||||
public static void AddImageAnnotation(this AnnotationManager manager, double x, double y, double width, double height, int page, string base64)
|
||||
{
|
||||
manager.SelectPage(page);
|
||||
manager.AddEmbeddedImageAnnotFromBase64(base64, (float)x, (float)y, (float)width, (float)height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="pAnnotation"></param>
|
||||
/// <param name="pAttachments"></param>
|
||||
public static void AddImageAnnotation(this AnnotationManager manager, Annotation pAnnotation, Dictionary<string, Attachment> pAttachments)
|
||||
{
|
||||
var oAttachment = pAttachments
|
||||
.Where(a => a.Key == pAnnotation.ImageAttachmentId)
|
||||
.SingleOrDefault();
|
||||
|
||||
if (oAttachment.Value == null)
|
||||
return;
|
||||
|
||||
// Convert pixels to Inches
|
||||
var oBounds = pAnnotation.Bbox?.Select(post => post.ToInches()).ToList();
|
||||
|
||||
if (oBounds is null || oBounds.Count < 4)
|
||||
return;
|
||||
|
||||
var oX = oBounds[0];
|
||||
var oY = oBounds[1];
|
||||
var oWidth = oBounds[2];
|
||||
var oHeight = oBounds[3];
|
||||
|
||||
manager.SelectPage(pAnnotation.PageIndex + 1);
|
||||
manager.AddEmbeddedImageAnnotFromBase64(oAttachment.Value.Binary, (float)oX, (float)oY, (float)oWidth, (float)oHeight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="page"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void AddInkAnnotation(this AnnotationManager manager, int page, string value)
|
||||
{
|
||||
var ink = JsonConvert.DeserializeObject<Ink>(value);
|
||||
|
||||
var oSegments = ink?.Lines.Points;
|
||||
var oColor = ColorTranslator.FromHtml(ink?.StrokeColor ?? "#000000");
|
||||
manager.SelectPage(page);
|
||||
|
||||
if (oSegments is null)
|
||||
return;
|
||||
|
||||
foreach (var oSegment in oSegments)
|
||||
{
|
||||
var oPoints = oSegment
|
||||
.Select(points => points.ToPointF())
|
||||
.ToArray();
|
||||
|
||||
manager.AddFreeHandAnnot(oColor, oPoints);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="pAnnotation"></param>
|
||||
public static void AddInkAnnotation(this AnnotationManager manager, Annotation pAnnotation)
|
||||
{
|
||||
var oSegments = pAnnotation.Lines?.Points;
|
||||
var oColor = ColorTranslator.FromHtml(pAnnotation.StrokeColor ?? "#000000");
|
||||
manager.SelectPage(pAnnotation.PageIndex + 1);
|
||||
|
||||
if (oSegments is null)
|
||||
return;
|
||||
|
||||
foreach (var oSegment in oSegments)
|
||||
{
|
||||
var oPoints = oSegment
|
||||
.Select(points => points.ToPointF())
|
||||
.ToArray();
|
||||
|
||||
manager.AddFreeHandAnnot(oColor, oPoints);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System.Drawing;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Extensions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class MathematExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="points"></param>
|
||||
/// <returns></returns>
|
||||
public static PointF ToPointF(this List<float> points)
|
||||
{
|
||||
var pointsInch = points.Select(ToInches).ToList();
|
||||
return new PointF(pointsInch[0], pointsInch[1]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static double ToInches(this double value)
|
||||
{
|
||||
return value / 72.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static float ToInches(this float value)
|
||||
{
|
||||
return value / 72f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Drawing;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Interfaces.Model;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public interface ITextStyle
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string FontName { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int FontSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>")]
|
||||
public FontStyle FontStyle { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using MediatR;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Notifications.RemoveSignature.Handlers;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class RemoveDocResult : INotificationHandler<RemoveSignatureNotification>
|
||||
{
|
||||
private readonly IRepository<Envelope> _repo;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repository"></param>
|
||||
public RemoveDocResult(IRepository<Envelope> repository)
|
||||
{
|
||||
_repo = repository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="notification"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public Task Handle(RemoveSignatureNotification notification, CancellationToken cancel)
|
||||
{
|
||||
if(notification.EnvelopeId is null && notification.EnvelopeUuid is null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
return _repo.UpdateAsync(
|
||||
envelope => envelope.DocResult = null,
|
||||
query => {
|
||||
if (notification.EnvelopeId is int envelopeId)
|
||||
query = query.Where(envelope => envelope.Id == envelopeId);
|
||||
|
||||
if (notification.EnvelopeUuid is string uuid)
|
||||
query = query.Where(envelope => envelope.Uuid == uuid);
|
||||
|
||||
return query;
|
||||
}, cancel);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,15 @@
|
||||
using EnvelopeGenerator.Application.Common.Configurations;
|
||||
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
||||
using EnvelopeGenerator.Application.Services;
|
||||
using EnvelopeGenerator.Application.ThirdPartyModules.Queries;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using QRCoder;
|
||||
using System.Reflection;
|
||||
using GdPicture14;
|
||||
|
||||
namespace EnvelopeGenerator.Application;
|
||||
|
||||
@@ -46,6 +50,28 @@ public static class DependencyInjection
|
||||
services.Configure<MailParams>(config.GetSection(nameof(MailParams)));
|
||||
services.Configure<AuthenticatorParams>(config.GetSection(nameof(AuthenticatorParams)));
|
||||
services.Configure<TotpSmsParams>(config.GetSection(nameof(TotpSmsParams)));
|
||||
services.Configure<PDFBurnerParams>(config.GetSection(nameof(PDFBurnerParams)));
|
||||
services.AddOptions<GdPictureParams>()
|
||||
.Configure((GdPictureParams opt, IServiceProvider sp) =>
|
||||
{
|
||||
var licenseKey = "GDPICTURE";
|
||||
using var scope = sp.CreateScope();
|
||||
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
|
||||
opt.License = config["GdPictureLicenseKey"]
|
||||
?? mediator.ReadThirdPartyModuleLicenseAsync(licenseKey).GetAwaiter().GetResult()
|
||||
?? throw new InvalidOperationException($"License record not found for key: {licenseKey}");
|
||||
});
|
||||
services.AddSingleton(provider => {
|
||||
var license = provider.GetRequiredService<IOptions<GdPictureParams>>().Value.License;
|
||||
var licenseManager = new LicenseManager();
|
||||
licenseManager.RegisterKEY(license);
|
||||
return licenseManager;
|
||||
});
|
||||
services.AddTransient(provider => {
|
||||
// Ensure LicenseManager is resolved so that its constructor is called
|
||||
_ = provider.GetRequiredService<LicenseManager>();
|
||||
return new AnnotationManager();
|
||||
});
|
||||
|
||||
services.AddHttpClientService<GtxMessagingParams>(config.GetSection(nameof(GtxMessagingParams)));
|
||||
services.TryAddSingleton<ISmsSender, GTXSmsSender>();
|
||||
@@ -58,6 +84,12 @@ public static class DependencyInjection
|
||||
cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly());
|
||||
});
|
||||
|
||||
// Add memory cache
|
||||
services.AddMemoryCache();
|
||||
|
||||
// Register mail services
|
||||
services.AddScoped<IEnvelopeMailService, EnvelopeMailService>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Dapper" Version="2.1.66" />
|
||||
<PackageReference Include="DigitalData.Core.Abstraction.Application" Version="1.4.0" />
|
||||
<PackageReference Include="DigitalData.Core.Abstraction.Application" Version="1.5.0" />
|
||||
<PackageReference Include="DigitalData.Core.Application" Version="3.4.0" />
|
||||
<PackageReference Include="DigitalData.Core.Client" Version="2.1.0" />
|
||||
<PackageReference Include="DigitalData.Core.Exceptions" Version="1.1.0" />
|
||||
@@ -25,23 +25,94 @@
|
||||
<PackageReference Include="Otp.NET" Version="1.4.0" />
|
||||
<PackageReference Include="QRCoder" Version="1.6.0" />
|
||||
<PackageReference Include="QRCoder-ImageSharp" Version="0.10.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.12" />
|
||||
<PackageReference Include="UserManager" Version="1.1.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||
<PackageReference Include="System.Formats.Asn1" Version="8.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
|
||||
<PackageReference Include="System.Formats.Asn1" Version="9.0.10" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
|
||||
<PackageReference Include="System.Formats.Asn1" Version="9.0.10" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj" />
|
||||
<ProjectReference Include="..\EnvelopeGenerator.PdfEditor\EnvelopeGenerator.PdfEditor.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="GdPicture.NET.14">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.barcode.1d.writer">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.barcode.1d.writer.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.barcode.2d.writer">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.barcode.2d.writer.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.CAD">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.CAD.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.CAD.DWG">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.CAD.DWG.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.Common">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.Document">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.Document.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.Email">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.Email.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.HTML">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.HTML.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.Imaging">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.Imaging.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.Imaging.Formats">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.Imaging.Formats.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.Imaging.Formats.Conversion">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.Imaging.Formats.Conversion.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.Imaging.Rendering">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.Imaging.Rendering.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.MSOfficeBinary">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.MSOfficeBinary.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.OpenDocument">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.OpenDocument.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.OpenXML">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.OpenXML.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.OpenXML.Templating">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.OpenXML.Templating.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.PDF">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.PDF.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.RTF">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.RTF.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.SVG">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.SVG.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14.wia.gateway">
|
||||
<HintPath>..\packages\GdPicture.14.3.3\lib\net462\GdPicture.NET.14.wia.gateway.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,18 +1,29 @@
|
||||
using MediatR;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using EnvelopeGenerator.Application.Common.Query;
|
||||
using EnvelopeGenerator.Application.Common.Dto;
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Application.Common.Extensions;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Envelopes.Queries;
|
||||
|
||||
/// <summary>
|
||||
/// Repräsentiert eine Abfrage für Umschläge.
|
||||
/// </summary>
|
||||
public record ReadEnvelopeQuery : EnvelopeQueryBase, IRequest
|
||||
public record ReadEnvelopeQuery : EnvelopeQueryBase, IRequest<IEnumerable<EnvelopeDto>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Abfrage des Include des Umschlags
|
||||
/// </summary>
|
||||
public EnvelopeStatusQuery? Status { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool? HasDocResult { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -65,4 +76,53 @@ public record EnvelopeStatusQuery
|
||||
/// Eine Liste von Statuswerten, die ignoriert werden werden.
|
||||
/// </summary>
|
||||
public EnvelopeStatus[]? Ignore { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadEnvelopeQueryHandler : IRequestHandler<ReadEnvelopeQuery, IEnumerable<EnvelopeDto>>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
private readonly IRepository<Envelope> _repo;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="mapper"></param>
|
||||
/// <param name="repo"></param>
|
||||
public ReadEnvelopeQueryHandler(IMapper mapper, IRepository<Envelope> repo)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_repo = repo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public async Task<IEnumerable<EnvelopeDto>> Handle(ReadEnvelopeQuery request, CancellationToken cancel)
|
||||
{
|
||||
var envelopesQ = _repo.Query.Where(request, notnull: false);
|
||||
|
||||
EnvelopeStatusQuery? statusQ = request.Status;
|
||||
bool? hasDocResult = request.HasDocResult;
|
||||
|
||||
var filtered =
|
||||
from envelope in envelopesQ
|
||||
where (statusQ == null || statusQ.Include == null || statusQ.Include.Contains(envelope.Status))
|
||||
&& (statusQ == null || statusQ.Ignore == null || !statusQ.Ignore.Contains(envelope.Status))
|
||||
&& (statusQ == null || statusQ.Min == null || envelope.Status > statusQ.Min)
|
||||
&& (statusQ == null || statusQ.Max == null || envelope.Status < statusQ.Max)
|
||||
&& (!hasDocResult.HasValue || (hasDocResult.Value ? envelope.DocResult != null : envelope.DocResult == null))
|
||||
select envelope;
|
||||
|
||||
var envelopes = await filtered.ToListAsync(cancel);
|
||||
|
||||
return _mapper.Map<IEnumerable<EnvelopeDto>>(envelopes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace EnvelopeGenerator.Application.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class BurnAnnotationException : ApplicationException
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public BurnAnnotationException(string message)
|
||||
: base(message) { }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public BurnAnnotationException(string message, Exception innerException)
|
||||
: base(message, innerException) { }
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class CreateReportException : ApplicationException
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public CreateReportException(string message)
|
||||
: base(message) { }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="innerException"></param>
|
||||
public CreateReportException(string message, Exception innerException)
|
||||
: base(message, innerException) { }
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace EnvelopeGenerator.Application.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ExportDocumentException : ApplicationException
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public ExportDocumentException(string message)
|
||||
: base(message) { }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="innerException"></param>
|
||||
public ExportDocumentException(string message, Exception innerException)
|
||||
: base(message, innerException) { }
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace EnvelopeGenerator.Application.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class MergeDocumentException : ApplicationException
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public MergeDocumentException(string message)
|
||||
: base(message) { }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="innerException"></param>
|
||||
public MergeDocumentException(string message, Exception innerException)
|
||||
: base(message, innerException) { }
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Histories.Queries;
|
||||
|
||||
//TODO: Add sender query
|
||||
/// <summary>
|
||||
/// Repräsentiert eine Abfrage für die Verlaufshistorie eines Umschlags.
|
||||
/// </summary>
|
||||
public record CountHistoryQuery : HistoryQueryBase, IRequest<int>;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class CountHistoryQueryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="uuid"></param>
|
||||
/// <param name="statuses"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<bool> AnyHistoryAsync(this ISender sender, string uuid, IEnumerable<EnvelopeStatus> statuses, CancellationToken cancel = default)
|
||||
{
|
||||
var count = await sender.Send(new CountHistoryQuery
|
||||
{
|
||||
Envelope = new() { Uuid = uuid },
|
||||
Statuses = new() { Include = statuses }
|
||||
}, cancel);
|
||||
return count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class CountHistoryQueryHandler : IRequestHandler<CountHistoryQuery, int>
|
||||
{
|
||||
private readonly IRepository<History> _repo;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repo"></param>
|
||||
public CountHistoryQueryHandler(IRepository<History> repo)
|
||||
{
|
||||
_repo = repo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotFoundException"></exception>
|
||||
public Task<int> Handle(CountHistoryQuery request, CancellationToken cancel = default)
|
||||
{
|
||||
var query = _repo.Query;
|
||||
|
||||
if (request.Envelope.Id is int envId)
|
||||
query = query.Where(e => e.Id == envId);
|
||||
else if (request.Envelope.Uuid is string uuid)
|
||||
query = query.Where(e => e.Envelope!.Uuid == uuid);
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
else if (request.EnvelopeId is not null)
|
||||
query = query.Where(h => h.EnvelopeId == request.EnvelopeId);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
else
|
||||
throw new BadRequestException("Invalid request: An Envelope object or a valid EnvelopeId/UUID must be supplied.");
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
if (request.Status is not null)
|
||||
query = query.Where(h => h.Status == request.Status);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
if (request.Statuses is not null)
|
||||
{
|
||||
var status = request.Statuses;
|
||||
if (status.Min is not null)
|
||||
query = query.Where(er => er.Envelope!.Status >= status.Min);
|
||||
|
||||
if (status.Max is not null)
|
||||
query = query.Where(er => er.Envelope!.Status <= status.Max);
|
||||
|
||||
if (status.Include?.Count() > 0)
|
||||
query = query.Where(er => status.Include.Contains(er.Envelope!.Status));
|
||||
|
||||
if (status.Ignore is not null)
|
||||
query = query.Where(er => !status.Ignore.Contains(er.Envelope!.Status));
|
||||
}
|
||||
|
||||
return query.CountAsync(cancel);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
using EnvelopeGenerator.Application.Common.Query;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Histories.Queries;
|
||||
|
||||
//TODO: Add sender query
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record HistoryQueryBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Die eindeutige Kennung des Umschlags.
|
||||
/// </summary>
|
||||
[Obsolete("Use Envelope property")]
|
||||
public int? EnvelopeId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Include des Umschlags, der abgefragt werden soll. Kann optional angegeben werden, um die Ergebnisse zu filtern.
|
||||
/// </summary>
|
||||
[Obsolete("Use statuses")]
|
||||
public EnvelopeStatus? Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public EnvelopeStatusQuery Statuses { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public EnvelopeQueryBase Envelope { get; set; } = new EnvelopeQueryBase();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record EnvelopeStatusQuery
|
||||
{
|
||||
/// <summary>
|
||||
/// Der minimale Statuswert, der berücksichtigt werden.
|
||||
/// </summary>
|
||||
public EnvelopeStatus? Min { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Der maximale Statuswert, der berücksichtigt werden.
|
||||
/// </summary>
|
||||
public EnvelopeStatus? Max { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Eine Liste von Statuswerten, die einbezogen werden.
|
||||
/// </summary>
|
||||
public IEnumerable<EnvelopeStatus>? Include { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Eine Liste von Statuswerten, die ignoriert werden werden.
|
||||
/// </summary>
|
||||
public IEnumerable<EnvelopeStatus>? Ignore { get; init; }
|
||||
}
|
||||
@@ -1,10 +1,7 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using EnvelopeGenerator.Application.Common.Dto.History;
|
||||
using EnvelopeGenerator.Application.Common.Dto.History;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using MediatR;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Histories.Queries;
|
||||
|
||||
@@ -12,81 +9,21 @@ namespace EnvelopeGenerator.Application.Histories.Queries;
|
||||
/// <summary>
|
||||
/// Repräsentiert eine Abfrage für die Verlaufshistorie eines Umschlags.
|
||||
/// </summary>
|
||||
public record ReadHistoryQuery : HistoryQueryBase, IRequest<IEnumerable<HistoryDto>>
|
||||
public record ReadHistoryQuery : IRequest<IEnumerable<HistoryDto>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Die eindeutige Kennung des Umschlags.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int EnvelopeId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Include des Umschlags, der abgefragt werden soll. Kann optional angegeben werden, um die Ergebnisse zu filtern.
|
||||
/// </summary>
|
||||
public EnvelopeStatus? Status { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Abfrage zur Steuerung, ob nur der aktuelle Include oder der gesamte Datensatz zurückgegeben wird.
|
||||
/// </summary>
|
||||
public bool OnlyLast { get; init; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadHistoryQueryHandler : IRequestHandler<ReadHistoryQuery, IEnumerable<HistoryDto>>
|
||||
{
|
||||
private readonly IRepository<History> _repo;
|
||||
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repo"></param>
|
||||
/// <param name="mapper"></param>
|
||||
public ReadHistoryQueryHandler(IRepository<History> repo, IMapper mapper)
|
||||
{
|
||||
_repo = repo;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotFoundException"></exception>
|
||||
public async Task<IEnumerable<HistoryDto>> Handle(ReadHistoryQuery request, CancellationToken cancel = default)
|
||||
{
|
||||
var query = _repo.Query;
|
||||
|
||||
if (request.Envelope.Id is int envId)
|
||||
query = query.Where(e => e.Id == envId);
|
||||
else if (request.Envelope.Uuid is string uuid)
|
||||
query = query.Where(e => e.Envelope!.Uuid == uuid);
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
else if (request.EnvelopeId is not null)
|
||||
query = query.Where(h => h.EnvelopeId == request.EnvelopeId);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
else
|
||||
throw new BadRequestException("Invalid request: An Envelope object or a valid EnvelopeId/UUID must be supplied.");
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
if (request.Status is not null)
|
||||
query = query.Where(h => h.Status == request.Status);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
if (request.Statuses is not null)
|
||||
{
|
||||
var status = request.Statuses;
|
||||
if (status.Min is not null)
|
||||
query = query.Where(er => er.Envelope!.Status >= status.Min);
|
||||
|
||||
if (status.Max is not null)
|
||||
query = query.Where(er => er.Envelope!.Status <= status.Max);
|
||||
|
||||
if (status.Include?.Count() > 0)
|
||||
query = query.Where(er => status.Include.Contains(er.Envelope!.Status));
|
||||
|
||||
if (status.Ignore is not null)
|
||||
query = query.Where(er => !status.Ignore.Contains(er.Envelope!.Status));
|
||||
}
|
||||
|
||||
if (request.OnlyLast)
|
||||
query = query.OrderByDescending(x => x.AddedWhen);
|
||||
|
||||
var hists = await query.ToListAsync(cancel);
|
||||
return _mapper.Map<List<HistoryDto>>(hists);
|
||||
}
|
||||
public bool? OnlyLast { get; init; } = true;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using EnvelopeGenerator.Application.Common.Dto.History;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Histories.Queries;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadHistoryQueryHandler : IRequestHandler<ReadHistoryQuery, IEnumerable<HistoryDto>>
|
||||
{
|
||||
private readonly IRepository<History> _repo;
|
||||
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repo"></param>
|
||||
/// <param name="mapper"></param>
|
||||
public ReadHistoryQueryHandler(IRepository<History> repo, IMapper mapper)
|
||||
{
|
||||
_repo = repo;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotFoundException"></exception>
|
||||
public async Task<IEnumerable<HistoryDto>> Handle(ReadHistoryQuery request, CancellationToken cancel = default)
|
||||
{
|
||||
var query = _repo.ReadOnly().Where(h => h.EnvelopeId == request.EnvelopeId);
|
||||
if (request.Status is not null)
|
||||
query = query.Where(h => h.Status == request.Status);
|
||||
|
||||
var hists = await query.ToListAsync(cancel);
|
||||
return _mapper.Map<List<HistoryDto>>(hists);
|
||||
}
|
||||
}
|
||||
241
EnvelopeGenerator.Application/Pdf/BurnPdfCommand.cs
Normal file
241
EnvelopeGenerator.Application/Pdf/BurnPdfCommand.cs
Normal file
@@ -0,0 +1,241 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Application.Common.Configurations;
|
||||
using EnvelopeGenerator.Application.Exceptions;
|
||||
using EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using GdPicture14;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
using EnvelopeGenerator.Application.Common.Extensions;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Pdf;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record BurnPdfCommand(byte[] Document, List<string> InstantJSONList, int EnvelopeId) : IRequest<byte[]>;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class BurnPdfCommandHandler : IRequestHandler<BurnPdfCommand, byte[]>
|
||||
{
|
||||
private readonly PDFBurnerParams _options;
|
||||
|
||||
private readonly AnnotationManager _manager;
|
||||
|
||||
private readonly IRepository<Signature> _signRepo;
|
||||
|
||||
private readonly ILogger<BurnPdfCommandHandler> _logger;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="pdfBurnerParams"></param>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="signRepo"></param>
|
||||
/// <param name="logger"></param>
|
||||
public BurnPdfCommandHandler(IOptions<PDFBurnerParams> pdfBurnerParams, AnnotationManager manager, IRepository<Signature> signRepo, ILogger<BurnPdfCommandHandler> logger)
|
||||
{
|
||||
_options = pdfBurnerParams.Value;
|
||||
_manager = manager;
|
||||
_signRepo = signRepo;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public async Task<byte[]> Handle(BurnPdfCommand request, CancellationToken cancel)
|
||||
{
|
||||
// read the elements of envelope with their annotations
|
||||
var elements = await _signRepo
|
||||
.Where(sig => sig.Document.EnvelopeId == request.EnvelopeId)
|
||||
.Include(sig => sig.Annotations)
|
||||
.ToListAsync(cancel);
|
||||
|
||||
return elements.Count > 0
|
||||
? BurnElementAnnotsToPDF(request.Document, elements)
|
||||
: BurnInstantJSONAnnotsToPDF(request.Document, request.InstantJSONList);
|
||||
}
|
||||
|
||||
private byte[] BurnElementAnnotsToPDF(byte[] pSourceBuffer, List<Signature> elements)
|
||||
{
|
||||
// Add background
|
||||
using var doc = PdfEditor.Pdf.FromMemory(pSourceBuffer);
|
||||
// TODO: take the length from the largest y
|
||||
pSourceBuffer = doc.Background(elements, 1.9500000000000002 * 0.93, 2.52 * 0.67)
|
||||
.ExportStream()
|
||||
.ToArray();
|
||||
|
||||
GdPictureStatus oResult;
|
||||
using var oSourceStream = new MemoryStream(pSourceBuffer);
|
||||
// Open PDF
|
||||
oResult = _manager.InitFromStream(oSourceStream);
|
||||
if (oResult != GdPictureStatus.OK)
|
||||
throw new BurnAnnotationException($"Could not open document for burning: [{oResult}]");
|
||||
|
||||
// Imported from background (add to configuration)
|
||||
var margin = 0.2;
|
||||
var inchFactor = 72;
|
||||
|
||||
// Y offset of form fields
|
||||
var keys = new[] { "position", "city", "date" }; // add to configuration
|
||||
var unitYOffsets = 0.2;
|
||||
|
||||
var yOffsetsOfFF = keys
|
||||
.Select((k, i) => new { Key = k, Value = unitYOffsets * i + 1 })
|
||||
.ToDictionary(x => x.Key, x => x.Value);
|
||||
|
||||
// Add annotations
|
||||
foreach (var element in elements)
|
||||
{
|
||||
var frameX = element.Left - 0.7 - margin;
|
||||
|
||||
var frame = element.Annotations?.FirstOrDefault(a => a.Name == "frame");
|
||||
var frameY = element.Top - 0.5 - margin;
|
||||
var frameYShift = (frame!.Y ?? default) - frameY * inchFactor;
|
||||
var frameXShift = (frame.X ?? default) - frameX * inchFactor;
|
||||
|
||||
foreach (var annot in element.Annotations!)
|
||||
{
|
||||
if (!yOffsetsOfFF.TryGetValue(annot.Name, out var yOffsetofFF))
|
||||
yOffsetofFF = 0;
|
||||
|
||||
var y = frameY + yOffsetofFF;
|
||||
|
||||
if (annot.Type == AnnotationType.PSPDFKit.FormField)
|
||||
{
|
||||
_manager.AddFormFieldValue(
|
||||
(annot.X ?? default) / inchFactor,
|
||||
y,
|
||||
(annot.Width ?? default) / inchFactor,
|
||||
(annot.Height ?? default) / inchFactor,
|
||||
element.Page,
|
||||
annot.Value,
|
||||
_options
|
||||
);
|
||||
}
|
||||
else if (annot.Type == AnnotationType.PSPDFKit.Image)
|
||||
{
|
||||
_manager.AddImageAnnotation(
|
||||
(annot.X ?? default) / inchFactor,
|
||||
annot.Name == "signature" ? ((annot.Y ?? default) - frameYShift) / inchFactor : y,
|
||||
(annot.Width ?? default) / inchFactor,
|
||||
(annot.Height ?? default) / inchFactor,
|
||||
element.Page,
|
||||
annot.Value
|
||||
);
|
||||
}
|
||||
else if (annot.Type == AnnotationType.PSPDFKit.Ink)
|
||||
{
|
||||
_manager.AddInkAnnotation(element.Page, annot.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save PDF
|
||||
using var oNewStream = new MemoryStream();
|
||||
oResult = _manager.SaveDocumentToPDF(oNewStream);
|
||||
if (oResult != GdPictureStatus.OK)
|
||||
throw new BurnAnnotationException($"Could not save document to stream: [{oResult}]");
|
||||
|
||||
_manager.Close();
|
||||
|
||||
return oNewStream.ToArray();
|
||||
}
|
||||
|
||||
private byte[] BurnInstantJSONAnnotsToPDF(byte[] pSourceBuffer, List<string> pInstantJSONList)
|
||||
{
|
||||
GdPictureStatus oResult;
|
||||
|
||||
using var oSourceStream = new MemoryStream(pSourceBuffer);
|
||||
// Open PDF
|
||||
oResult = _manager.InitFromStream(oSourceStream);
|
||||
if (oResult != GdPictureStatus.OK)
|
||||
{
|
||||
throw new BurnAnnotationException($"Could not open document for burning: [{oResult}]");
|
||||
}
|
||||
|
||||
// Add annotation to PDF
|
||||
foreach (var oJSON in pInstantJSONList)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (oJSON is string json)
|
||||
AddInstantJsonAnnotationToPdf(json);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning("Error in AddInstantJSONAnnotationToPDF - oJson: ");
|
||||
_logger.LogWarning(oJSON);
|
||||
throw new BurnAnnotationException("Adding Annotation failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
oResult = _manager.BurnAnnotationsToPage(RemoveInitialAnnots: true, VectorMode: true);
|
||||
if (oResult != GdPictureStatus.OK)
|
||||
{
|
||||
throw new BurnAnnotationException($"Could not burn annotations to file: [{oResult}]");
|
||||
}
|
||||
|
||||
// Save PDF
|
||||
using var oNewStream = new MemoryStream();
|
||||
oResult = _manager.SaveDocumentToPDF(oNewStream);
|
||||
if (oResult != GdPictureStatus.OK)
|
||||
{
|
||||
throw new BurnAnnotationException($"Could not save document to stream: [{oResult}]");
|
||||
}
|
||||
|
||||
_manager.Close();
|
||||
|
||||
return oNewStream.ToArray();
|
||||
}
|
||||
|
||||
private void AddInstantJsonAnnotationToPdf(string instantJson)
|
||||
{
|
||||
var annotationData = JsonConvert.DeserializeObject<InstantData>(instantJson);
|
||||
|
||||
annotationData?.Annotations?.Reverse();
|
||||
|
||||
if (annotationData?.Annotations is null)
|
||||
return;
|
||||
|
||||
foreach (var annotation in annotationData.Annotations)
|
||||
{
|
||||
_logger.LogDebug("Adding AnnotationID: {id}", annotation.Id);
|
||||
|
||||
switch (annotation.Type)
|
||||
{
|
||||
case AnnotationType.PSPDFKit.Image:
|
||||
if (annotationData?.Attachments is not null)
|
||||
_manager.AddImageAnnotation(annotation, annotationData.Attachments);
|
||||
break;
|
||||
|
||||
case AnnotationType.PSPDFKit.Ink:
|
||||
_manager.AddInkAnnotation(annotation);
|
||||
break;
|
||||
|
||||
case AnnotationType.PSPDFKit.Widget:
|
||||
// Add form field values
|
||||
var formFieldValue = annotationData?.FormFieldValues?
|
||||
.FirstOrDefault(fv => fv.Name == annotation.Id);
|
||||
|
||||
if (formFieldValue != null && !_options.IgnoredLabels.Contains(formFieldValue.Value))
|
||||
{
|
||||
_manager.AddFormFieldValue(annotation, formFieldValue, _options);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Application.Common.Dto;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace EnvelopeGenerator.Application.ThirdPartyModules.Queries;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record ReadThirdPartyModuleQuery : IRequest<IEnumerable<ThirdPartyModuleDto>>
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool? Active { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record ReadThirdPartyModuleQueryHandler : IRequestHandler<ReadThirdPartyModuleQuery, IEnumerable<ThirdPartyModuleDto>>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
private readonly IRepository<ThirdPartyModule> _repo;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="mapper"></param>
|
||||
/// <param name="repo"></param>
|
||||
public ReadThirdPartyModuleQueryHandler(IMapper mapper, IRepository<ThirdPartyModule> repo)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_repo = repo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public async Task<IEnumerable<ThirdPartyModuleDto>> Handle(ReadThirdPartyModuleQuery request, CancellationToken cancel)
|
||||
{
|
||||
var query = _repo.Query;
|
||||
|
||||
if(request.Name is string name)
|
||||
query = query.Where(m => m.Name == name);
|
||||
|
||||
if (request.Active is bool active)
|
||||
query = query.Where(m => m.Active == active);
|
||||
|
||||
var modules = await query.ToListAsync(cancel);
|
||||
|
||||
return _mapper.Map<IEnumerable<ThirdPartyModuleDto>>(modules);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class ReadThirdPartyModuleQueryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="mediator"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="active"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string?> ReadThirdPartyModuleLicenseAsync(this IMediator mediator, string name, bool active = true, CancellationToken cancel = default)
|
||||
{
|
||||
var modules = await mediator.Send(new ReadThirdPartyModuleQuery()
|
||||
{
|
||||
Name = name,
|
||||
Active = active,
|
||||
}, cancel);
|
||||
|
||||
return modules.FirstOrDefault()?.License;
|
||||
}
|
||||
}
|
||||
@@ -70,8 +70,8 @@
|
||||
<Reference Include="DigitalData.Controls.DocumentViewer, Version=1.9.8.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DigitalData.Controls.DocumentViewer.1.9.8\lib\net462\DigitalData.Controls.DocumentViewer.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DigitalData.Core.Abstraction.Application, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DigitalData.Core.Abstraction.Application.1.4.0\lib\net462\DigitalData.Core.Abstraction.Application.dll</HintPath>
|
||||
<Reference Include="DigitalData.Core.Abstraction.Application, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DigitalData.Core.Abstraction.Application.1.5.0\lib\net462\DigitalData.Core.Abstraction.Application.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DigitalData.Core.Abstractions, Version=4.3.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DigitalData.Core.Abstractions.4.3.0\lib\net462\DigitalData.Core.Abstractions.dll</HintPath>
|
||||
|
||||
@@ -32,7 +32,7 @@ Public Class frmFinalizePDF
|
||||
#Disable Warning BC40000 ' Type or member is obsolete
|
||||
Factory.Shared _
|
||||
.BehaveOnPostBuild(PostBuildBehavior.Ignore) _
|
||||
.AddEnvelopeGeneratorInfrastructureServices(
|
||||
.AddEGInfrastructureServices(
|
||||
Sub(opt)
|
||||
opt.AddDbTriggerParams(
|
||||
Sub(triggers)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<package id="AutoMapper" version="10.1.1" targetFramework="net462" />
|
||||
<package id="BouncyCastle.Cryptography" version="2.5.0" targetFramework="net462" />
|
||||
<package id="DigitalData.Controls.DocumentViewer" version="1.9.8" targetFramework="net462" />
|
||||
<package id="DigitalData.Core.Abstraction.Application" version="1.4.0" targetFramework="net462" />
|
||||
<package id="DigitalData.Core.Abstraction.Application" version="1.5.0" targetFramework="net462" />
|
||||
<package id="DigitalData.Core.Abstractions" version="4.3.0" targetFramework="net462" />
|
||||
<package id="DigitalData.Modules.Base" version="1.3.8" targetFramework="net462" />
|
||||
<package id="DigitalData.Modules.Config" version="1.3.0" targetFramework="net462" />
|
||||
|
||||
@@ -72,8 +72,8 @@
|
||||
<Reference Include="DevExpress.XtraEditors.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
|
||||
<Reference Include="DevExpress.XtraGauges.v21.2.Core, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL" />
|
||||
<Reference Include="DevExpress.XtraReports.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL" />
|
||||
<Reference Include="DigitalData.Core.Abstraction.Application, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DigitalData.Core.Abstraction.Application.1.4.0\lib\net462\DigitalData.Core.Abstraction.Application.dll</HintPath>
|
||||
<Reference Include="DigitalData.Core.Abstraction.Application, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DigitalData.Core.Abstraction.Application.1.5.0\lib\net462\DigitalData.Core.Abstraction.Application.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DigitalData.Core.Abstractions, Version=4.3.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DigitalData.Core.Abstractions.4.3.0\lib\net462\DigitalData.Core.Abstractions.dll</HintPath>
|
||||
|
||||
@@ -72,7 +72,7 @@ Namespace Jobs
|
||||
#Disable Warning BC40000 ' Type or member is obsolete
|
||||
Factory.Shared _
|
||||
.BehaveOnPostBuild(PostBuildBehavior.Ignore) _
|
||||
.AddEnvelopeGeneratorInfrastructureServices(
|
||||
.AddEGInfrastructureServices(
|
||||
Sub(opt)
|
||||
opt.AddDbTriggerParams(
|
||||
Sub(triggers)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<packages>
|
||||
<package id="AutoMapper" version="10.1.1" targetFramework="net462" />
|
||||
<package id="BouncyCastle.Cryptography" version="2.5.0" targetFramework="net462" />
|
||||
<package id="DigitalData.Core.Abstraction.Application" version="1.4.0" targetFramework="net462" />
|
||||
<package id="DigitalData.Core.Abstraction.Application" version="1.5.0" targetFramework="net462" />
|
||||
<package id="DigitalData.Core.Abstractions" version="4.3.0" targetFramework="net462" />
|
||||
<package id="DigitalData.Modules.Base" version="1.3.8" targetFramework="net462" />
|
||||
<package id="DigitalData.Modules.Config" version="1.3.0" targetFramework="net462" />
|
||||
|
||||
98
EnvelopeGenerator.DependencyInjection/DependencyInjection.cs
Normal file
98
EnvelopeGenerator.DependencyInjection/DependencyInjection.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
using DigitalData.EmailProfilerDispatcher;
|
||||
using DigitalData.UserManager.DependencyInjection;
|
||||
using EnvelopeGenerator.Application;
|
||||
using EnvelopeGenerator.Infrastructure;
|
||||
using Microsoft.Extensions.Caching.SqlServer;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using static EnvelopeGenerator.Infrastructure.DependencyInjection;
|
||||
|
||||
namespace EnvelopeGenerator.DependencyInjection;
|
||||
|
||||
public static class DependencyInjection
|
||||
{
|
||||
public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, Action<EGConfiguration> options)
|
||||
{
|
||||
var egConfig = new EGConfiguration();
|
||||
options.Invoke(egConfig);
|
||||
egConfig.EnsureAllServicesConfigured();
|
||||
egConfig.RegisterAll(services);
|
||||
|
||||
// Add envelope generator services
|
||||
#pragma warning disable CS0618
|
||||
services.AddUserManager<EGDbContext>();
|
||||
#pragma warning restore CS0618
|
||||
|
||||
services.AddDispatcher<EGDbContext>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public record EGConfiguration
|
||||
{
|
||||
internal readonly Queue<Action<IServiceCollection>> _serviceRegs = new();
|
||||
|
||||
internal void RegisterAll(IServiceCollection services)
|
||||
{
|
||||
while (_serviceRegs.Count > 0)
|
||||
_serviceRegs.Dequeue().Invoke(services);
|
||||
}
|
||||
|
||||
// TODO: update to use attributes and reflections instead of _addingStatus-dictionary
|
||||
private readonly Dictionary<string, bool> _addingStatus = new ()
|
||||
{
|
||||
{ nameof(AddLocalization), false },
|
||||
{ nameof(AddDistributedSqlServerCache), false },
|
||||
{ nameof(AddInfrastructure), false },
|
||||
{ nameof(AddServices), false },
|
||||
};
|
||||
|
||||
public EGConfiguration AddLocalization(Action<IServiceCollection>? customLocalizationOptions = null)
|
||||
{
|
||||
_serviceRegs.Enqueue(customLocalizationOptions ?? (s => s.AddLocalization()));
|
||||
_addingStatus[nameof(AddLocalization)] = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EGConfiguration AddDistributedSqlServerCache(Action<SqlServerCacheOptions> setupAction)
|
||||
{
|
||||
_serviceRegs.Enqueue(s => s.AddDistributedSqlServerCache(setupAction));
|
||||
_addingStatus[nameof(AddDistributedSqlServerCache)] = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EGConfiguration AddInfrastructure(Action<EGInfrastructureConfiguration> options)
|
||||
{
|
||||
#pragma warning disable CS0618
|
||||
_serviceRegs.Enqueue(s => s.AddEGInfrastructureServices(options));
|
||||
#pragma warning restore CS0618
|
||||
_addingStatus[nameof(AddInfrastructure)] = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EGConfiguration AddServices(IConfiguration config)
|
||||
{
|
||||
#pragma warning disable CS0618
|
||||
_serviceRegs.Enqueue(s => s.AddEnvelopeGeneratorServices(config));
|
||||
#pragma warning restore CS0618
|
||||
_addingStatus[nameof(AddServices)] = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
internal void EnsureAllServicesConfigured()
|
||||
{
|
||||
var missingServices = _addingStatus
|
||||
.Where(kv => !kv.Value)
|
||||
.Select(kv => kv.Key)
|
||||
.ToList();
|
||||
|
||||
if (missingServices.Count > 0)
|
||||
{
|
||||
var missingList = string.Join(", ", missingServices);
|
||||
throw new InvalidOperationException(
|
||||
$"Service configuration incomplete. The following required service methods were not called: {missingList}. " +
|
||||
"Please ensure all necessary configuration methods are invoked before building the application.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="9.0.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.10" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Application\EnvelopeGenerator.Application.csproj" />
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
13
EnvelopeGenerator.Domain/Constants/AnnotationType.cs
Normal file
13
EnvelopeGenerator.Domain/Constants/AnnotationType.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace EnvelopeGenerator.Domain.Constants
|
||||
{
|
||||
public static class AnnotationType
|
||||
{
|
||||
public static class PSPDFKit
|
||||
{
|
||||
public const string Image = "pspdfkit/image";
|
||||
public const string Ink = "pspdfkit/ink";
|
||||
public const string Widget = "pspdfkit/widget";
|
||||
public const string FormField = "pspdfkit/form-field-value";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
|
||||
#if NETFRAMEWORK
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -134,14 +133,12 @@ public class Envelope
|
||||
= false;
|
||||
#endif
|
||||
|
||||
[NotMapped]
|
||||
[Column("DOC_RESULT")]
|
||||
public byte[]
|
||||
#if NET
|
||||
?
|
||||
#endif
|
||||
DocResult
|
||||
{ get; set; }
|
||||
DocResult { get; set; }
|
||||
|
||||
[ForeignKey("EnvelopeTypeId")]
|
||||
public virtual EnvelopeType
|
||||
|
||||
@@ -5,6 +5,8 @@ using System.ComponentModel.DataAnnotations.Schema;
|
||||
#if NETFRAMEWORK
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#elif NET
|
||||
using System.Text.Json.Serialization;
|
||||
#endif
|
||||
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
@@ -120,13 +122,17 @@ public class Signature : ISignature, IHasReceiver
|
||||
#endif
|
||||
Annotations { get; set; }
|
||||
|
||||
#if NETFRAMEWORK
|
||||
#if NET
|
||||
[JsonIgnore]
|
||||
#endif
|
||||
[NotMapped]
|
||||
public double Top => Math.Round(Y, 5);
|
||||
|
||||
#if NET
|
||||
[JsonIgnore]
|
||||
#endif
|
||||
[NotMapped]
|
||||
public double Left => Math.Round(X, 5);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETFRAMEWORK
|
||||
|
||||
73
EnvelopeGenerator.Domain/Entities/ThirdPartyModule.cs
Normal file
73
EnvelopeGenerator.Domain/Entities/ThirdPartyModule.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
#if NETFRAMEWORK
|
||||
using System;
|
||||
#endif
|
||||
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
{
|
||||
[Table("TBDD_3RD_PARTY_MODULES")]
|
||||
public class ThirdPartyModule
|
||||
{
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
[Column("GUID")]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("ACTIVE")]
|
||||
public bool Active { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(50)]
|
||||
[Column("NAME")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[StringLength(500)]
|
||||
[Column("DESCRIPTION")]
|
||||
public string
|
||||
#if nullable
|
||||
?
|
||||
#endif
|
||||
Description { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("LICENSE", TypeName = "varchar(max)")]
|
||||
public string License { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(20)]
|
||||
[Column("VERSION")]
|
||||
public string Version { get; set; }
|
||||
|
||||
[StringLength(50)]
|
||||
[Column("ADDED_WHO")]
|
||||
public string
|
||||
#if nullable
|
||||
?
|
||||
#endif
|
||||
AddedWho { get; set; }
|
||||
|
||||
[Column("ADDED_WHEN")]
|
||||
public DateTime
|
||||
#if nullable
|
||||
?
|
||||
#endif
|
||||
AddedWhen { get; set; }
|
||||
|
||||
[StringLength(50)]
|
||||
[Column("CHANGED_WHO")]
|
||||
public string
|
||||
#if nullable
|
||||
?
|
||||
#endif
|
||||
ChangedWho { get; set; }
|
||||
|
||||
[Column("CHANGED_WHEN")]
|
||||
public DateTime
|
||||
#if nullable
|
||||
?
|
||||
#endif
|
||||
ChangedWhen { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UserSecretsId>dotnet-EnvelopeGenerator.Finalizer-6d5cc618-4159-4ff2-b600-8a15fbfa8099</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Quartz.AspNetCore" Version="3.15.1" />
|
||||
<PackageReference Include="Quartzmon" Version="1.0.5" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
|
||||
<PackageReference Include="Quartz" Version="3.15.1" />
|
||||
<PackageReference Include="Quartz.Extensions.Hosting" Version="3.15.1" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Application\EnvelopeGenerator.Application.csproj" />
|
||||
<ProjectReference Include="..\EnvelopeGenerator.DependencyInjection\EnvelopeGenerator.DependencyInjection.csproj" />
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Controllers\" />
|
||||
<Folder Include="Controllers\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="appsettings.Database.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="appsettings.Logging.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
35
EnvelopeGenerator.Finalizer/Extensions.cs
Normal file
35
EnvelopeGenerator.Finalizer/Extensions.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using EnvelopeGenerator.Finalizer.Job;
|
||||
using Quartz;
|
||||
|
||||
namespace EnvelopeGenerator.Finalizer;
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
public static IServiceCollectionQuartzConfigurator ScheduleJobDefault<TJob>(this IServiceCollectionQuartzConfigurator q,
|
||||
string croneEpression)
|
||||
where TJob : IJob
|
||||
{
|
||||
var name = $"{typeof(TJob).FullName}";
|
||||
var jobKey = new JobKey(name);
|
||||
|
||||
return q.ScheduleJob<TJob>(trigger => trigger
|
||||
.WithIdentity(name + "-trigger")
|
||||
.WithCronSchedule(croneEpression),
|
||||
job => job.WithIdentity(jobKey)
|
||||
);
|
||||
}
|
||||
|
||||
public static IServiceCollectionQuartzConfigurator ScheduleJobDefault<TJob>(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<TJob>(expression);
|
||||
}
|
||||
}
|
||||
24
EnvelopeGenerator.Finalizer/Job/EnvelopeTaskApiJob.cs
Normal file
24
EnvelopeGenerator.Finalizer/Job/EnvelopeTaskApiJob.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using Quartz;
|
||||
|
||||
namespace EnvelopeGenerator.Finalizer.Job
|
||||
{
|
||||
public class EnvelopeTaskApiJob : IJob
|
||||
{
|
||||
private readonly ILogger<EnvelopeTaskApiJob> _logger;
|
||||
|
||||
public EnvelopeTaskApiJob(ILogger<EnvelopeTaskApiJob> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
if (_logger.IsEnabled(LogLevel.Information))
|
||||
{
|
||||
_logger.LogInformation("{jobName} running at: {time}", context.JobDetail.Key, DateTimeOffset.Now);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
55
EnvelopeGenerator.Finalizer/Job/FinishEnvelopeJob.cs
Normal file
55
EnvelopeGenerator.Finalizer/Job/FinishEnvelopeJob.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using EnvelopeGenerator.Application.Envelopes.Queries;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using EnvelopeGenerator.Finalizer.Models;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Quartz;
|
||||
|
||||
namespace EnvelopeGenerator.Finalizer.Job
|
||||
{
|
||||
public class FinishEnvelopeJob : IJob
|
||||
{
|
||||
private readonly ILogger<FinishEnvelopeJob> _logger;
|
||||
|
||||
private readonly GdPictureOptions _gdPictureOptions;
|
||||
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
public FinishEnvelopeJob(ILogger<FinishEnvelopeJob> logger, IOptions<GdPictureOptions> gdPictureOptions, IMediator mediator)
|
||||
{
|
||||
_logger = logger;
|
||||
_gdPictureOptions = gdPictureOptions.Value;
|
||||
_mediator = mediator;
|
||||
}
|
||||
|
||||
public async Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
var cancel = context.CancellationToken;
|
||||
|
||||
var envelopes = await _mediator.Send(new ReadEnvelopeQuery()
|
||||
{
|
||||
Status = new() { Include = [EnvelopeStatus.EnvelopeCompletelySigned] },
|
||||
HasDocResult = false
|
||||
}, cancel);
|
||||
|
||||
foreach (var envelope in envelopes)
|
||||
{
|
||||
// add sub-steps
|
||||
}
|
||||
|
||||
if (envelopes.Any())
|
||||
_logger.LogInformation(
|
||||
"Job '{JobName}' executed at {Timestamp}. {EnvelopeCount} envelope(s) successfully finalized. UUID(s): {EnvelopeUuids}",
|
||||
context.JobDetail.Key.Name,
|
||||
DateTimeOffset.Now,
|
||||
envelopes.Count(),
|
||||
string.Join(", ", envelopes.Select(e => e.Uuid))
|
||||
);
|
||||
else
|
||||
_logger.LogInformation("Job '{JobName}' executed successfully at {Timestamp}. No envelopes were finalized.",
|
||||
context.JobDetail.Key.Name,
|
||||
DateTimeOffset.Now
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
134
EnvelopeGenerator.Finalizer/Program.cs
Normal file
134
EnvelopeGenerator.Finalizer/Program.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using CommandDotNet.Execution;
|
||||
using EnvelopeGenerator.Application.ThirdPartyModules.Queries;
|
||||
using EnvelopeGenerator.DependencyInjection;
|
||||
using EnvelopeGenerator.Finalizer;
|
||||
using EnvelopeGenerator.Finalizer.Job;
|
||||
using EnvelopeGenerator.Finalizer.Models;
|
||||
using EnvelopeGenerator.Infrastructure;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Quartz;
|
||||
using Quartz.AspNetCore;
|
||||
using Quartz.Impl;
|
||||
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<FinishEnvelopeJob>(config);
|
||||
q.ScheduleJobDefault<EnvelopeTaskApiJob>(config);
|
||||
});
|
||||
|
||||
builder.Services.AddQuartzServer(options =>
|
||||
{
|
||||
options.WaitForJobsToComplete = true;
|
||||
});
|
||||
|
||||
builder.Services.AddQuartzmon();
|
||||
|
||||
builder.Services.AddSingleton(provider =>
|
||||
provider.GetRequiredService<ISchedulerFactory>().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<ILogger<EGDbContext>>();
|
||||
var useInMemoryDb = config.GetValue<bool>("UseInMemoryDb");
|
||||
var dbCtxOpt = useInMemoryDb ? options.UseInMemoryDatabase("EGInMemoryDb") : options.UseSqlServer(connStr);
|
||||
dbCtxOpt.LogTo(log => logger.LogInformation("{log}", log), LogLevel.Trace)
|
||||
.EnableSensitiveDataLogging()
|
||||
.EnableDetailedErrors();
|
||||
});
|
||||
})
|
||||
.AddServices(config)
|
||||
);
|
||||
#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<IScheduler>(),
|
||||
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();
|
||||
}
|
||||
41
EnvelopeGenerator.Finalizer/Properties/launchSettings.json
Normal file
41
EnvelopeGenerator.Finalizer/Properties/launchSettings.json
Normal file
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
22
EnvelopeGenerator.Finalizer/appsettings.Database.json
Normal file
22
EnvelopeGenerator.Finalizer/appsettings.Database.json
Normal file
@@ -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
|
||||
}
|
||||
8
EnvelopeGenerator.Finalizer/appsettings.Development.json
Normal file
8
EnvelopeGenerator.Finalizer/appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
}
|
||||
}
|
||||
8
EnvelopeGenerator.Finalizer/appsettings.Job.json
Normal file
8
EnvelopeGenerator.Finalizer/appsettings.Job.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"FinishEnvelopeJob": {
|
||||
"CronExpression": "* * * * * ?"
|
||||
},
|
||||
"EnvelopeTaskApiJob": {
|
||||
"CronExpression": "* * * * * ?"
|
||||
}
|
||||
}
|
||||
81
EnvelopeGenerator.Finalizer/appsettings.Logging.json
Normal file
81
EnvelopeGenerator.Finalizer/appsettings.Logging.json
Normal file
@@ -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" ]
|
||||
}
|
||||
}
|
||||
14
EnvelopeGenerator.Finalizer/appsettings.PdfBurner.json
Normal file
14
EnvelopeGenerator.Finalizer/appsettings.PdfBurner.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"IgnoredLabels": {
|
||||
"Label": [
|
||||
"Date",
|
||||
"Datum",
|
||||
"ZIP",
|
||||
"PLZ",
|
||||
"Place",
|
||||
"Ort",
|
||||
"Position",
|
||||
"Stellung"
|
||||
]
|
||||
}
|
||||
}
|
||||
3
EnvelopeGenerator.Finalizer/appsettings.json
Normal file
3
EnvelopeGenerator.Finalizer/appsettings.json
Normal file
@@ -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=="
|
||||
}
|
||||
@@ -105,6 +105,7 @@ try
|
||||
});
|
||||
builder.Services.AddOpenApi();
|
||||
|
||||
// TODO: Update to configure with EnvelopeGenerator.DependencyInjection
|
||||
//AddEF Core dbcontext
|
||||
var useDbMigration = Environment.GetEnvironmentVariable("MIGRATION_TEST_MODE") == true.ToString() || config.GetValue<bool>("UseDbMigration");
|
||||
var cnnStrName = useDbMigration ? "DbMigrationTest" : "Default";
|
||||
@@ -185,7 +186,7 @@ try
|
||||
// Envelope generator serives
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
builder.Services
|
||||
.AddEnvelopeGeneratorInfrastructureServices(opt =>
|
||||
.AddEGInfrastructureServices(opt =>
|
||||
{
|
||||
opt.AddDbTriggerParams(config);
|
||||
opt.AddDbContext((provider, options) =>
|
||||
|
||||
@@ -38,10 +38,10 @@ namespace EnvelopeGenerator.Infrastructure
|
||||
/// will be created per HTTP request (or per scope) within the dependency injection container.
|
||||
/// </remarks>
|
||||
[Obsolete("Use IRepository")]
|
||||
public static IServiceCollection AddEnvelopeGeneratorInfrastructureServices(this IServiceCollection services, Action<Config> options)
|
||||
public static IServiceCollection AddEGInfrastructureServices(this IServiceCollection services, Action<EGInfrastructureConfiguration> options)
|
||||
{
|
||||
// configure custom options
|
||||
options(new Config(services));
|
||||
options(new EGInfrastructureConfiguration(services));
|
||||
#if NET
|
||||
services.TryAddScoped<IConfigRepository, ConfigRepository>();
|
||||
services.TryAddScoped<IDocumentReceiverElementRepository, DocumentReceiverElementRepository>();
|
||||
@@ -160,11 +160,11 @@ namespace EnvelopeGenerator.Infrastructure
|
||||
}
|
||||
#endif
|
||||
|
||||
public class Config
|
||||
public class EGInfrastructureConfiguration
|
||||
{
|
||||
private readonly IServiceCollection _services;
|
||||
|
||||
internal Config(IServiceCollection services)
|
||||
internal EGInfrastructureConfiguration(IServiceCollection services)
|
||||
{
|
||||
_services = services;
|
||||
}
|
||||
|
||||
@@ -79,6 +79,8 @@ public abstract class EGDbContextBase : DbContext
|
||||
|
||||
public DbSet<ClientUser> ClientUsers { get; set; }
|
||||
|
||||
public DbSet<ThirdPartyModule> ThirdPartyModules { get; set; }
|
||||
|
||||
private readonly DbTriggerParams _triggers;
|
||||
|
||||
private readonly ILogger
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Dapper" Version="2.1.66" />
|
||||
<PackageReference Include="DigitalData.Core.Abstraction.Application" Version="1.4.0" />
|
||||
<PackageReference Include="DigitalData.Core.Infrastructure" Version="2.4.5" />
|
||||
<PackageReference Include="DigitalData.Core.Abstraction.Application" Version="1.5.0" />
|
||||
<PackageReference Include="DigitalData.Core.Infrastructure" Version="2.5.0" />
|
||||
<PackageReference Include="QuestPDF" Version="2025.7.1" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -525,7 +525,7 @@ namespace EnvelopeGenerator.Infrastructure.Migrations
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EnvelopeGenerator.Domain.Entities.Config", b =>
|
||||
modelBuilder.Entity("EnvelopeGenerator.Domain.Entities.EGInfrastructureConfiguration", b =>
|
||||
{
|
||||
b.Property<string>("ExportPath")
|
||||
.HasColumnType("nvarchar(256)")
|
||||
|
||||
@@ -522,7 +522,7 @@ namespace EnvelopeGenerator.Infrastructure.Migrations
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EnvelopeGenerator.Domain.Entities.Config", b =>
|
||||
modelBuilder.Entity("EnvelopeGenerator.Domain.Entities.EGInfrastructureConfiguration", b =>
|
||||
{
|
||||
b.Property<string>("ExportPath")
|
||||
.HasColumnType("nvarchar(256)")
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Bogus" Version="35.6.3" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||
<PackageReference Include="DigitalData.Core.Abstraction.Application" Version="1.4.0" />
|
||||
<PackageReference Include="DigitalData.Core.Abstraction.Application" Version="1.5.0" />
|
||||
<PackageReference Include="DigitalData.Core.Abstractions" Version="4.3.0" />
|
||||
<PackageReference Include="DigitalData.Core.API" Version="2.2.1" />
|
||||
<PackageReference Include="DigitalData.Core.Application" Version="3.4.0" />
|
||||
|
||||
@@ -4,7 +4,6 @@ using EnvelopeGenerator.Application.Common.Extensions;
|
||||
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
||||
using EnvelopeGenerator.Application.Common.Notifications.DocSigned;
|
||||
using EnvelopeGenerator.Application.EnvelopeReceivers.Queries;
|
||||
using EnvelopeGenerator.Application.Histories.Queries;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using EnvelopeGenerator.Web.Extensions;
|
||||
using MediatR;
|
||||
@@ -12,6 +11,7 @@ using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Dynamic;
|
||||
|
||||
namespace EnvelopeGenerator.Web.Controllers;
|
||||
|
||||
@@ -58,9 +58,7 @@ public class AnnotationController : ControllerBase
|
||||
|
||||
// Again check if receiver has already signed
|
||||
if (await _mediator.IsSignedAsync(uuid, signature, cancel))
|
||||
return Problem(statusCode: 409);
|
||||
else if (await _mediator.AnyHistoryAsync(uuid, new[] { EnvelopeStatus.EnvelopeRejected, EnvelopeStatus.DocumentRejected }, cancel))
|
||||
return Problem(statusCode: 423);
|
||||
return Problem(statusCode: 403);
|
||||
|
||||
var docSignedNotification = await _mediator
|
||||
.ReadEnvelopeReceiverAsync(uuid, signature, cancel)
|
||||
@@ -73,7 +71,7 @@ public class AnnotationController : ControllerBase
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
||||
[Authorize(Roles = ReceiverRole.FullyAuth)]
|
||||
[HttpPost("reject")]
|
||||
[Obsolete("Use DigitalData.Core.Exceptions and .Middleware")]
|
||||
|
||||
@@ -95,23 +95,6 @@ public class EnvelopeController : ViewControllerBase
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UseAccessCode
|
||||
if (!er.Envelope!.UseAccessCode)
|
||||
{
|
||||
(string? uuid, string? signature) = decoded.ParseEnvelopeReceiverId();
|
||||
var er_secret_res = await _envRcvService.ReadWithSecretByUuidSignatureAsync(uuid: uuid!, signature: signature!);
|
||||
|
||||
if (er_secret_res.IsFailed)
|
||||
{
|
||||
_logger.LogNotice(er_secret_res.Notices);
|
||||
return this.ViewEnvelopeNotFound();
|
||||
}
|
||||
var er_secret = er_secret_res.Data;
|
||||
await HttpContext.SignInEnvelopeAsync(er_secret, ReceiverRole.FullyAuth);
|
||||
return await CreateShowEnvelopeView(er_secret);
|
||||
}
|
||||
#endregion UseAccessCode
|
||||
|
||||
#region Send Access Code
|
||||
bool accessCodeAlreadyRequested = await _historyService.AccessCodeAlreadyRequested(envelopeId: er.Envelope!.Id, userReference: er.Receiver!.EmailAddress);
|
||||
if (!accessCodeAlreadyRequested)
|
||||
@@ -138,7 +121,7 @@ public class EnvelopeController : ViewControllerBase
|
||||
|
||||
[HttpPost("{envelopeReceiverId}")]
|
||||
[Obsolete("Use MediatR")]
|
||||
public async Task<IActionResult> LogInEnvelope([FromRoute] string envelopeReceiverId, [FromForm] Auth auth, CancellationToken cancel)
|
||||
public async Task<IActionResult> LogInEnvelope([FromRoute] string envelopeReceiverId, [FromForm] Auth auth)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -162,15 +145,6 @@ public class EnvelopeController : ViewControllerBase
|
||||
}
|
||||
var er_secret = er_secret_res.Data;
|
||||
|
||||
//check rejection
|
||||
var rejRcvrs = await _historyService.ReadRejectingReceivers(er_secret.Envelope!.Id);
|
||||
if (rejRcvrs.Any())
|
||||
{
|
||||
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
ViewBag.IsExt = !rejRcvrs.Contains(er_secret.Receiver); //external if the current user is not rejected
|
||||
return View("EnvelopeRejected", er_secret);
|
||||
}
|
||||
|
||||
// show envelope if already logged in
|
||||
if (User.IsInRole(ReceiverRole.FullyAuth))
|
||||
return await CreateShowEnvelopeView(er_secret);
|
||||
@@ -216,7 +190,7 @@ public class EnvelopeController : ViewControllerBase
|
||||
return this.ViewInnerServiceError();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async Task<IActionResult> CreateEnvelopeLockedView(EnvelopeReceiverDto er, CancellationToken cancel)
|
||||
{
|
||||
var uuidClaim = User.GetAuthEnvelopeUuid();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<PackageId>EnvelopeGenerator.Web</PackageId>
|
||||
@@ -12,9 +12,9 @@
|
||||
<PackageTags>digital data envelope generator web</PackageTags>
|
||||
<Description>EnvelopeGenerator.Web is an ASP.NET MVC application developed to manage signing processes. It uses Entity Framework Core (EF Core) for database operations. The user interface for signing processes is developed with Razor View Engine (.cshtml files) and JavaScript under wwwroot, integrated with PSPDFKit. This integration allows users to view and sign documents seamlessly.</Description>
|
||||
<ApplicationIcon>Assets\icon.ico</ApplicationIcon>
|
||||
<Version>3.7.0</Version>
|
||||
<AssemblyVersion>3.7.0</AssemblyVersion>
|
||||
<FileVersion>3.7.0</FileVersion>
|
||||
<Version>3.5.0</Version>
|
||||
<AssemblyVersion>3.5.0</AssemblyVersion>
|
||||
<FileVersion>3.5.0</FileVersion>
|
||||
<Copyright>Copyright © 2025 Digital Data GmbH. All rights reserved.</Copyright>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -2094,13 +2094,20 @@
|
||||
<None Include="wwwroot\lib\bootstrap-icons\icons\zoom-out.svg" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
||||
<PackageReference Include="BuildBundlerMinifier2022" Version="2.9.9" />
|
||||
<PackageReference Include="DigitalData.Core.API" Version="2.2.1" />
|
||||
<PackageReference Include="DigitalData.Core.Exceptions" Version="1.1.0" />
|
||||
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.1.1" />
|
||||
<PackageReference Include="HtmlSanitizer" Version="8.0.865" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.20" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.15">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.20" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="7.0.20" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.2.5" />
|
||||
@@ -2119,56 +2126,6 @@
|
||||
<PackageReference Include="System.Security.Cryptography.Cng" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
||||
<PackageReference Include="BuildBundlerMinifier2022" Version="2.9.9" />
|
||||
<PackageReference Include="DigitalData.Core.API" Version="2.2.1" />
|
||||
<PackageReference Include="DigitalData.Core.Exceptions" Version="1.1.0" />
|
||||
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.1.1" />
|
||||
<PackageReference Include="HtmlSanitizer" Version="8.0.865" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="7.0.20" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.2.5" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="5.3.0" />
|
||||
<PackageReference Include="Quartz" Version="3.8.0" />
|
||||
<PackageReference Include="Quartz.AspNetCore" Version="3.8.0" />
|
||||
<PackageReference Include="Quartz.Plugins" Version="3.8.0" />
|
||||
<PackageReference Include="Quartz.Serialization.Json" Version="3.8.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.0.1" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="8.0.1" />
|
||||
<PackageReference Include="System.Diagnostics.PerformanceCounter" Version="7.0.0" />
|
||||
<PackageReference Include="System.DirectoryServices" Version="8.0.0" />
|
||||
<PackageReference Include="System.DirectoryServices.AccountManagement" Version="8.0.1" />
|
||||
<PackageReference Include="System.DirectoryServices.Protocols" Version="8.0.1" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="8.0.16" />
|
||||
<PackageReference Include="System.Security.Cryptography.Cng" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
|
||||
<PackageReference Include="BuildBundlerMinifier2022" Version="2.9.9" />
|
||||
<PackageReference Include="DigitalData.Core.API" Version="2.2.1" />
|
||||
<PackageReference Include="DigitalData.Core.Exceptions" Version="1.1.0" />
|
||||
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.1.1" />
|
||||
<PackageReference Include="HtmlSanitizer" Version="8.0.865" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="7.0.20" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.2.5" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="5.3.0" />
|
||||
<PackageReference Include="Quartz" Version="3.8.0" />
|
||||
<PackageReference Include="Quartz.AspNetCore" Version="3.8.0" />
|
||||
<PackageReference Include="Quartz.Plugins" Version="3.8.0" />
|
||||
<PackageReference Include="Quartz.Serialization.Json" Version="3.8.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.0.1" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="9.0.11" />
|
||||
<PackageReference Include="System.Diagnostics.PerformanceCounter" Version="7.0.0" />
|
||||
<PackageReference Include="System.DirectoryServices" Version="9.0.4" />
|
||||
<PackageReference Include="System.DirectoryServices.AccountManagement" Version="9.0.4" />
|
||||
<PackageReference Include="System.DirectoryServices.Protocols" Version="9.0.4" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="9.0.5" />
|
||||
<PackageReference Include="System.Security.Cryptography.Cng" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Application\EnvelopeGenerator.Application.csproj" />
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj" />
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using EnvelopeGenerator.Application.Services;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NLog;
|
||||
using Quartz;
|
||||
@@ -16,7 +15,6 @@ using EnvelopeGenerator.Web.Sanitizers;
|
||||
using EnvelopeGenerator.Web.Models.Annotation;
|
||||
using DigitalData.UserManager.DependencyInjection;
|
||||
using EnvelopeGenerator.Web.Middleware;
|
||||
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
||||
|
||||
var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
|
||||
logger.Info("Logging initialized!");
|
||||
@@ -88,6 +86,7 @@ try
|
||||
builder.Services.AddSwaggerGen();
|
||||
}
|
||||
|
||||
// TODO: Update to configure with EnvelopeGenerator.DependencyInjection
|
||||
//AddEF Core dbcontext
|
||||
var useDbMigration = Environment.GetEnvironmentVariable("MIGRATION_TEST_MODE") == true.ToString() || config.GetValue<bool>("UseDbMigration");
|
||||
var cnnStrName = useDbMigration ? "DbMigrationTest" : "Default";
|
||||
@@ -103,7 +102,7 @@ try
|
||||
|
||||
// Add envelope generator services
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
builder.Services.AddEnvelopeGeneratorInfrastructureServices(
|
||||
builder.Services.AddEGInfrastructureServices(
|
||||
opt =>
|
||||
{
|
||||
opt.AddDbTriggerParams(config);
|
||||
@@ -186,15 +185,8 @@ try
|
||||
builder.Services.Configure<Cultures>(config.GetSection("Cultures"));
|
||||
builder.Services.AddSingleton(sp => sp.GetRequiredService<IOptions<Cultures>>().Value);
|
||||
|
||||
// Register mail services
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
builder.Services.AddScoped<IEnvelopeMailService, EnvelopeMailService>();
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
builder.Services.AddDispatcher<EGDbContext>();
|
||||
|
||||
builder.Services.AddMemoryCache();
|
||||
|
||||
builder.ConfigureBySection<CustomImages>();
|
||||
|
||||
builder.ConfigureBySection<AnnotationParams>();
|
||||
|
||||
@@ -11,10 +11,12 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
|
||||
<ExcludeApp_Data>false</ExcludeApp_Data>
|
||||
<ProjectGuid>5e0e17c0-ff5a-4246-bf87-1add85376a27</ProjectGuid>
|
||||
<DesktopBuildPackageLocation>P:\Install .Net\0 DD - Smart UP\signFLOW\Web\net8\$(Version)\EnvelopeGenerator.Web.zip</DesktopBuildPackageLocation>
|
||||
<DesktopBuildPackageLocation>P:\Install .Net\0 DD - Smart UP\signFLOW\Web\net9\win64\$(Version)\EnvelopeGenerator.Web.zip</DesktopBuildPackageLocation>
|
||||
<PackageAsSingleFile>true</PackageAsSingleFile>
|
||||
<DeployIisAppPath>EnvelopeGenerator</DeployIisAppPath>
|
||||
<_TargetId>IISWebDeployPackage</_TargetId>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<SelfContained>true</SelfContained>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -79,7 +79,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="markdown">@(envelope?.Message)</div>
|
||||
<h6>@($"{@envelope?.Message}")</h6>
|
||||
}
|
||||
<p>
|
||||
<small class="text-body-secondary">
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.min.js"></script>
|
||||
<script src="~/lib/sweetalert2/sweetalert2.min.js"></script>
|
||||
<script src="~/lib/alertifyjs/alertify.min.js"></script>
|
||||
<script src="~/lib/marked/marked.umd.min.js"></script>
|
||||
<script src="~/js/lazy.min.js" asp-append-version="true"></script>
|
||||
<script src="~/js/ui.min.js" asp-append-version="true"></script>
|
||||
<script src="~/js/annotation.js" asp-append-version="true"></script>
|
||||
@@ -96,6 +95,5 @@
|
||||
</div>
|
||||
<a href="/privacy-policy.@(_localizer.Culture()).html" target="_blank">@_localizer.Privacy()</a>
|
||||
</footer>
|
||||
<script src="~/js/markdown.min.js" asp-append-version="true"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -41,12 +41,6 @@
|
||||
"wwwroot/js/util.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"outputFileName": "wwwroot/js/markdown.min.js",
|
||||
"inputFiles": [
|
||||
"wwwroot/js/markdown.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"outputFileName": "wwwroot/css/error-space.min.css",
|
||||
"inputFiles": [
|
||||
|
||||
@@ -255,7 +255,7 @@ class App {
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
if (res.status === 409) {
|
||||
if (res.status === 403) {
|
||||
Swal.fire({
|
||||
title: 'Warnung',
|
||||
text: 'Umschlag ist nicht mehr verfügbar.',
|
||||
@@ -263,17 +263,6 @@ class App {
|
||||
})
|
||||
return false
|
||||
}
|
||||
else if (res.status === 423) {
|
||||
Swal.fire({
|
||||
title: 'Info',
|
||||
text: 'Dokument wurde von einem Empfänger abgelehnt. Sie werden weitergeleitet...',
|
||||
icon: 'info',
|
||||
timer: 2000,
|
||||
showConfirmButton: false
|
||||
}).then(() => {
|
||||
location.reload();
|
||||
});
|
||||
}
|
||||
else {
|
||||
throw new Error()
|
||||
}
|
||||
|
||||
2
EnvelopeGenerator.Web/wwwroot/js/app.min.js
vendored
2
EnvelopeGenerator.Web/wwwroot/js/app.min.js
vendored
@@ -1,3 +1,3 @@
|
||||
class App{constructor(n,t,i,r,u,f){this.container=f??`#${this.constructor.name.toLowerCase()}`;this.envelopeKey=n;this.pdfKit=null;this.currentDocument=t.envelope.documents[0];this.currentReceiver=t.receiver;this.signatureCount=t.envelope.documents[0].elements.length;this.envelopeReceiver=t;this.documentBytes=i;this.licenseKey=r;this.locale=u}async init(){this.pdfKit=await loadPSPDFKit(this.documentBytes,this.container,this.licenseKey,this.locale);addToolbarItems(this.pdfKit,this.handleClick.bind(this));this.pdfKit.addEventListener("annotations.load",this.handleAnnotationsLoad.bind(this));this.pdfKit.addEventListener("annotations.change",this.handleAnnotationsChange.bind(this));this.pdfKit.addEventListener("annotations.create",this.handleAnnotationsCreate.bind(this));this.pdfKit.addEventListener("annotations.willChange",()=>{Comp.ActPanel.Toggle()});try{let n=await createAnnotations(this.currentDocument,this.envelopeReceiver.envelopeId,this.envelopeReceiver.receiverId);await this.pdfKit.create(n)}catch(n){console.error("Error loading annotations:",n)}[...document.getElementsByClassName("btn_refresh")].forEach(n=>n.addEventListener("click",()=>this.handleClick("RESET")));[...document.getElementsByClassName("btn_complete")].forEach(n=>n.addEventListener("click",()=>this.handleClick("FINISH")));[...document.getElementsByClassName("btn_reject")].forEach(n=>n.addEventListener("click",()=>this.handleClick("REJECT")))}handleAnnotationsLoad(n){n.toJS()}handleAnnotationsChange(){}async handleAnnotationsCreate(n){const t=n.toJS()[0],i=!!t.formFieldName,r=!!t.isSignature;if(i===!1&&r===!0){const r=t.boundingBox.left-20,u=t.boundingBox.top-20,n=150,i=75,f=new Date,e=await createAnnotationFrameBlob(this.envelopeReceiver.name,this.currentReceiver.signature,f,n,i),o=await fetch(e),s=await o.blob(),h=await this.pdfKit.createAttachment(s),c=createImageAnnotation(new PSPDFKit.Geometry.Rect({left:r,top:u,width:n,height:i}),t.pageIndex,h,generateId(this.envelopeReceiver.envelopeId,this.envelopeReceiver.receiverId,this.fakeElementId--,"signed"));this.pdfKit.create(c)}}async handleClick(n){let t=!1;switch(n){case"RESET":t=await this.handleReset(null);Comp.SignatureProgress.SignedCount=0;t.isConfirmed&&Swal.fire({title:"Erfolg",text:"Dokument wurde zurückgesetzt",icon:"info"});break;case"FINISH":t=await this.handleFinish(null);t==!0&&(window.location.href=`/Envelope/${this.envelopeKey}`);break;case"REJECT":Swal.fire({title:localized.rejection,html:`<div class="text-start fs-6 p-0 m-0">${localized.rejectionReasonQ}</div>`,icon:"question",input:"text",inputAttributes:{autocapitalize:"off"},showCancelButton:!0,confirmButtonColor:"#3085d6",cancelButtonColor:"#d33",confirmButtonText:localized.complete,cancelButtonText:localized.back,showLoaderOnConfirm:!0,preConfirm:async n=>{try{return await rejectEnvelope(n)}catch(t){Swal.showValidationMessage(`
|
||||
Request failed: ${t}
|
||||
`)}},allowOutsideClick:()=>!Swal.isLoading()}).then(n=>{if(n.isConfirmed){const t=n.value;t.ok?reload():Swal.showValidationMessage(`Request failed: ${t.message}`)}});break;case"COPY_URL":const n=window.location.href.replace(/\/readonly/gi,"");navigator.clipboard.writeText(n).then(function(){bsNotify("Kopiert",{alert_type:"success",delay:4,icon_name:"check_circle"})}).catch(function(){bsNotify("Unerwarteter Fehler",{alert_type:"danger",delay:4,icon_name:"error"})});break;case"SHARE":Comp.ShareBackdrop.show();break;case"LOGOUT":await logout()}}async handleFinish(){const n=await this.pdfKit.exportInstantJSON(),t=n.formFieldValues,r=t.filter(n=>isFieldRequired(n)),u=r.some(n=>n.value===undefined||n.value===null||n.value==="");if(u)return Swal.fire({title:"Warnung",text:"Bitte füllen Sie alle Standortinformationen vollständig aus!",icon:"warning"}),!1;const f=new RegExp("^[a-zA-Z\\u0080-\\u024F]+(?:([\\ \\-\\']|(\\.\\ ))[a-zA-Z\\u0080-\\u024F]+)*$"),e=t.filter(n=>isCityField(n));for(var i of e)if(!IS_MOBILE_DEVICE&&!f.test(i.value))return Swal.fire({title:"Warnung",text:`Bitte überprüfen Sie die eingegebene Ortsangabe "${i.value}" auf korrekte Formatierung. Beispiele für richtige Formate sind: München, Île-de-France, Sauðárkrókur, San Francisco, St. Catharines usw.`,icon:"warning"}),!1;const o=await this.validateAnnotations(this.signatureCount);return o===!1?(Swal.fire({title:"Warnung",text:"Es wurden nicht alle Signaturfelder ausgefüllt!",icon:"warning"}),!1):Swal.fire({title:localized.confirmation,html:`<div class="text-start fs-6 p-0 m-0">${localized.sigAgree}</div>`,icon:"question",showCancelButton:!0,confirmButtonColor:"#3085d6",cancelButtonColor:"#d33",confirmButtonText:localized.finalize,cancelButtonText:localized.back}).then(async t=>{if(t.isConfirmed){try{await this.pdfKit.save()}catch(i){return Swal.fire({title:"Fehler",text:"Umschlag konnte nicht signiert werden!",icon:"error"}),!1}try{const t=await signEnvelope({instant:n,structured:mapSignature(n)});if(t.ok)return!0;if(t.status===409)return Swal.fire({title:"Warnung",text:"Umschlag ist nicht mehr verfügbar.",icon:"warning"}),!1;if(t.status===423)Swal.fire({title:"Info",text:"Dokument wurde von einem Empfänger abgelehnt. Sie werden weitergeleitet...",icon:"info",timer:2e3,showConfirmButton:!1}).then(()=>{location.reload()});else throw new Error;}catch(i){return Swal.fire({title:"Fehler",text:"Umschlag konnte nicht signiert werden!",icon:"error"}),!1}}else return!1})}async validateAnnotations(n){const t=await getAnnotations(this.pdfKit),i=t.map(n=>n.toJS()).filter(n=>n.isSignature);return n<=i.length}async handleReset(){const n=Swal.fire({title:"Sind sie sicher?",text:"Wollen Sie das Dokument und alle erstellten Signaturen zurücksetzen?",icon:"question",showCancelButton:!0});if(n.isConfirmed){const n=await deleteAnnotations(this.pdfKit)}return n}fakeElementId=0;}
|
||||
`)}},allowOutsideClick:()=>!Swal.isLoading()}).then(n=>{if(n.isConfirmed){const t=n.value;t.ok?reload():Swal.showValidationMessage(`Request failed: ${t.message}`)}});break;case"COPY_URL":const n=window.location.href.replace(/\/readonly/gi,"");navigator.clipboard.writeText(n).then(function(){bsNotify("Kopiert",{alert_type:"success",delay:4,icon_name:"check_circle"})}).catch(function(){bsNotify("Unerwarteter Fehler",{alert_type:"danger",delay:4,icon_name:"error"})});break;case"SHARE":Comp.ShareBackdrop.show();break;case"LOGOUT":await logout()}}async handleFinish(){const n=await this.pdfKit.exportInstantJSON(),t=n.formFieldValues,r=t.filter(n=>isFieldRequired(n)),u=r.some(n=>n.value===undefined||n.value===null||n.value==="");if(u)return Swal.fire({title:"Warnung",text:"Bitte füllen Sie alle Standortinformationen vollständig aus!",icon:"warning"}),!1;const f=new RegExp("^[a-zA-Z\\u0080-\\u024F]+(?:([\\ \\-\\']|(\\.\\ ))[a-zA-Z\\u0080-\\u024F]+)*$"),e=t.filter(n=>isCityField(n));for(var i of e)if(!IS_MOBILE_DEVICE&&!f.test(i.value))return Swal.fire({title:"Warnung",text:`Bitte überprüfen Sie die eingegebene Ortsangabe "${i.value}" auf korrekte Formatierung. Beispiele für richtige Formate sind: München, Île-de-France, Sauðárkrókur, San Francisco, St. Catharines usw.`,icon:"warning"}),!1;const o=await this.validateAnnotations(this.signatureCount);return o===!1?(Swal.fire({title:"Warnung",text:"Es wurden nicht alle Signaturfelder ausgefüllt!",icon:"warning"}),!1):Swal.fire({title:localized.confirmation,html:`<div class="text-start fs-6 p-0 m-0">${localized.sigAgree}</div>`,icon:"question",showCancelButton:!0,confirmButtonColor:"#3085d6",cancelButtonColor:"#d33",confirmButtonText:localized.finalize,cancelButtonText:localized.back}).then(async t=>{if(t.isConfirmed){try{await this.pdfKit.save()}catch(i){return Swal.fire({title:"Fehler",text:"Umschlag konnte nicht signiert werden!",icon:"error"}),!1}try{const t=await signEnvelope({instant:n,structured:mapSignature(n)});if(t.ok)return!0;if(t.status===403)return Swal.fire({title:"Warnung",text:"Umschlag ist nicht mehr verfügbar.",icon:"warning"}),!1;throw new Error;}catch(i){return Swal.fire({title:"Fehler",text:"Umschlag konnte nicht signiert werden!",icon:"error"}),!1}}else return!1})}async validateAnnotations(n){const t=await getAnnotations(this.pdfKit),i=t.map(n=>n.toJS()).filter(n=>n.isSignature);return n<=i.length}async handleReset(){const n=Swal.fire({title:"Sind sie sicher?",text:"Wollen Sie das Dokument und alle erstellten Signaturen zurücksetzen?",icon:"question",showCancelButton:!0});if(n.isConfirmed){const n=await deleteAnnotations(this.pdfKit)}return n}fakeElementId=0;}
|
||||
@@ -1,11 +0,0 @@
|
||||
marked.use({
|
||||
async: true,
|
||||
breaks: true,
|
||||
gfm: true,
|
||||
});
|
||||
|
||||
(async () => {
|
||||
for (const el of document.querySelectorAll('.markdown')) {
|
||||
el.innerHTML = await marked.parse(el.textContent.replace(/(\t| )/g, " "));
|
||||
}
|
||||
})();
|
||||
@@ -1 +0,0 @@
|
||||
marked.use({"async":!0,breaks:!0,gfm:!0});(async()=>{for(const n of document.querySelectorAll(".markdown"))n.innerHTML=await marked.parse(n.textContent.replace(/(\t| )/g," "))})();
|
||||
File diff suppressed because one or more lines are too long
@@ -37,6 +37,10 @@ Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "EnvelopeGenerator.Form", "E
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnvelopeGenerator.PdfEditor", "EnvelopeGenerator.PdfEditor\EnvelopeGenerator.PdfEditor.csproj", "{211619F5-AE25-4BA5-A552-BACAFE0632D3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnvelopeGenerator.DependencyInjection", "EnvelopeGenerator.DependencyInjection\EnvelopeGenerator.DependencyInjection.csproj", "{B97DE7DD-3190-4A84-85E9-E57AD735BE61}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnvelopeGenerator.Finalizer", "EnvelopeGenerator.Finalizer\EnvelopeGenerator.Finalizer.csproj", "{C4970E6C-DB2E-48C5-B3C5-2AF589405ED9}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -91,6 +95,14 @@ Global
|
||||
{211619F5-AE25-4BA5-A552-BACAFE0632D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{211619F5-AE25-4BA5-A552-BACAFE0632D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{211619F5-AE25-4BA5-A552-BACAFE0632D3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B97DE7DD-3190-4A84-85E9-E57AD735BE61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B97DE7DD-3190-4A84-85E9-E57AD735BE61}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B97DE7DD-3190-4A84-85E9-E57AD735BE61}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B97DE7DD-3190-4A84-85E9-E57AD735BE61}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C4970E6C-DB2E-48C5-B3C5-2AF589405ED9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{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
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -111,6 +123,8 @@ Global
|
||||
{A9F9B431-BB9B-49B8-9E2C-0703634A653A} = {E3C758DC-914D-4B7E-8457-0813F1FDB0CB}
|
||||
{6D56C01F-D6CB-4D8A-BD3D-4FD34326998C} = {E3C758DC-914D-4B7E-8457-0813F1FDB0CB}
|
||||
{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}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {73E60370-756D-45AD-A19A-C40A02DACCC7}
|
||||
|
||||
Reference in New Issue
Block a user