Compare commits

369 Commits

Author SHA1 Message Date
6195d99fab refactor: remove usePdfBurner parameter from AddEnvelopeGeneratorServices 2025-11-12 16:55:06 +01:00
50a372a224 feat(CCommonServicces.FinalizeDocument.PDFMerger): update to use SaveToStream instead of ConvertToPDFA 2025-11-12 16:27:20 +01:00
35dd2e8e07 refactor(email): replace Task.WhenAll with foreach in SendEmailBehavior
Changed the SendFinalEmailToReceiversAsync method to use a sequential `foreach` loop
instead of `Task.WhenAll` for sending history commands. Added a null check for
receiver emails to prevent potential exceptions.
2025-11-12 16:14:32 +01:00
fac5419589 refactor: simplify email sending logic and remove debug checks
- Removed unused `EnvelopeGenerator.Domain.Entities` import.
- Changed `SendFinalEmailWithAttachment` calls to explicitly cast envelope email type to `int`.
- Removed `Debug` conditional checks around history creation; history commands are now always sent.
- Made `SendFinalEmailWithAttachment` a static method for clarity.
2025-11-12 15:44:37 +01:00
d442ad0ce0 refactor(SendEmailBehavior): update to add history recors when request is not debug 2025-11-12 15:35:23 +01:00
cbe2acc37d feat(SendEmailBehavior): make SendEmailBehavior fully async and record history
- Added ISender dependency to send history commands
- Refactored SendFinalEmailToCreator and SendFinalEmailToReceivers to async
- Log attachment inclusion for emails
- Use Task.WhenAll for sending to multiple receivers
2025-11-12 15:32:06 +01:00
40cc467b47 feat(SendEmailBehavior): add SendEmailBehavior for sending final emails after PDF burn
- Implements IPipelineBehavior<BurnPdfCommand, byte[]> to send emails to creator and receivers.
- Logs debug information when sending emails and warnings if email sending is skipped.
- Uses Envelope's FinalEmailType to determine whether to send emails.
2025-11-12 15:12:04 +01:00
d1513dab5e feat(WritePdfBehavior): add WritePdfBehavior to handle PDF writing pipeline
- Implements WritePdfBehavior as an IPipelineBehavior for BurnPdfCommand
- Writes generated PDF to configured export path
- Automatically creates export directory if missing
- Adds logging for export path and file operations
2025-11-12 14:55:35 +01:00
dee424e7db feat(DefaultReadConfigQuery): add DefaultReadConfigQuery with caching and AutoMapper support
- Implemented DefaultReadConfigQuery and its handler for reading default configuration.
- Added memory caching using IMemoryCache to improve performance.
- Integrated AutoMapper to map Config entities to ConfigDto.
- Included extension method for easier MediatR query invocation.
- Added error handling for missing configuration records.
2025-11-12 14:34:30 +01:00
e57e9e1834 fix(PdfMergeBehavior): improve error diagnostics and exception messages in PdfMergeBehavior
- Added detailed request context to all MergeDocumentException messages
- Clarified conversion error message from "converted to PDF/A" to "converted to byte"
- Removed unused base64 conversion and redundant variable assignment
- Improved code readability and string concatenation formatting
2025-11-12 14:02:40 +01:00
5b30465126 refactor(pdf): simplify and inline PDF merge logic in PdfMergeBehavior
- Removed MergeDocuments static method; integrated merge process directly in Handle()
- Added null check for request.Report before merging
- Cleaned up redundant return and improved flow for memory stream handling
- Added DevExpress.XtraReports using directive
- Clarified comment and exception messages for PDF loading and merging
2025-11-12 13:59:35 +01:00
2dfa1de7e1 refactor(PdfMergeBehavior): update to use SaveToStream instead of ConvertToPDFA 2025-11-12 13:51:49 +01:00
e68965543e refactor(BurnPdfCommand): add Report property to forward report.
- Reverse the order in which behaviors are added.
2025-11-12 12:47:19 +01:00
958bcdfc42 chore: wrap AddReportBehavior with #if WINDOWS directive 2025-11-12 11:08:09 +01:00
d88ed324be refactor(Pdf\Behaviors): Handle the history recording process in another behavior named CreateHistoryBehavior 2025-11-12 11:00:24 +01:00
380b141738 refactor(project): add net8.0-windows target and unify net8.0 package references
- Updated <TargetFrameworks> to include net8.0-windows
- Consolidated package references for net8.0 and net8.0-windows into a single ItemGroup
2025-11-12 10:51:04 +01:00
f3a15216a8 chore: update TargetFramework to net8.0-windows in project file 2025-11-12 10:43:18 +01:00
8a48bf6b51 feat(EnvelopeGenerator.Finalizer.Win): Create to process window-oriented services 2025-11-12 10:17:37 +01:00
0038eeed76 feat(EGDbContextBase): add EnvelopeReports-property 2025-11-11 23:31:35 +01:00
4ed118ed2b update to add as closed behavior 2025-11-11 23:24:51 +01:00
Developer 02
350aa259c8 chore(Application): add DevExpress.Reporting.Core 2025-11-11 23:16:36 +01:00
Developer 02
737de2202e remove unnecessary projects 2025-11-11 23:08:50 +01:00
Developer 02
ff60cd7ef8 refactor: simplify AddReportBehavior by making DoCreateReport static and reordering base64 conversion 2025-11-11 22:57:50 +01:00
Developer 02
e1aa7fe650 chore(Application): add CommonServices reference 2025-11-11 22:51:14 +01:00
Developer 02
9c0b1e3fa8 chore(App.VB): fix reference 2025-11-11 22:33:46 +01:00
6b34b55c4f chore(Application.VB): add System.Drawing.Common and DevExpress-packages 2025-11-11 22:22:47 +01:00
4a5608249e refactor(Application.VB): add dev express dependencies 2025-11-11 21:59:27 +01:00
Developer 02
965838513f create EnvelopeGenerator.Application.VB 2025-11-11 21:49:56 +01:00
Developer 02
9c4766518e feat(AddReportBehavior): add PDF report generation logic with logging
- Introduced `ILogger<AddReportBehavior>` for logging support.
- Added `DoCreateReport` method to generate PDF from `EnvelopeReport` items.
- Added `ReportSource` class to structure report data.
- Retained existing history creation and MediatR pipeline behavior.
2025-11-11 21:40:20 +01:00
Developer 02
292b6b2ccf feat(AddReportBehavior): add report creation logic to AddReportBehavior
- Added CreateReport method to generate PDF report from envelope data
- Integrated call to CreateReport within pipeline after history creation
- Introduced error handling via CreateReportException for missing report data
- Added necessary using directives for EnvelopeReports, Exceptions, and Entities
2025-11-11 21:19:21 +01:00
Developer 02
6f9b5d4b13 feat(envelope-reports): add extension method for reading envelope reports via ISender 2025-11-11 19:21:22 +01:00
Developer 02
8459706c45 feat: implement ReadEnvelopeReportQuery with handler and repository integration
- Add ReadEnvelopeReportQuery record that returns IEnumerable<EnvelopeReport>
- Implement ReadEnvelopeReportQueryHandler with repository and AutoMapper integration
- Add ThrowIfNotFound property with JsonIgnore and NotMapped attributes
- Integrate IRepository<EnvelopeReport> for data access
- Add NotFoundException when no reports found and ThrowIfNotFound is true
- Configure Entity Framework Core using Microsoft.EntityFrameworkCore
- Add JSON serialization configuration with System.Text.Json
- Update using statements with necessary abstractions and exceptions
2025-11-11 18:22:23 +01:00
Developer 02
972c63388e add EnvelopeReport to EnvelopeReportDto mapping 2025-11-11 17:34:42 +01:00
Developer 02
cde9ed06a1 create EnvelopeReportDto 2025-11-11 17:32:52 +01:00
Developer 02
d94f885e92 init a query to read envelope report by envelope id via mediator 2025-11-11 17:27:46 +01:00
Developer 02
028785a8c9 create EnvelopeReport-entity 2025-11-11 17:11:32 +01:00
Developer 02
e6285f13f7 feat(AddReportBehavior): add conditional history creation based on Debug flag in AddReportBehavior 2025-11-11 13:08:34 +01:00
35b7b1a080 refactor(AddReportBehavior): update to add history record. 2025-11-10 17:05:35 +01:00
67d0980c63 move the behaviours about pdf to pdf dir 2025-11-10 16:46:10 +01:00
c6a99b56a2 add GdPicture packages via nuget 2025-11-10 16:18:42 +01:00
31f5d1f340 add SaveBurnedPdfBehavior to services 2025-11-10 15:29:16 +01:00
a2df5d7691 create SaveBurnedPdfBehavior 2025-11-10 15:13:57 +01:00
f8c586dd31 feat(FinishEnvelopeJob): add PDF burning with concurrency control
- Introduced PDFBurnerParams configuration for concurrency limit.
- Added SemaphoreSlim to handle concurrent PDF burning for envelopes.
- Updated job to call _mediator.BurnPdf for each envelope with error handling.
- Preserved logging of job execution and envelope UUIDs.
2025-11-10 15:01:07 +01:00
8aea3c8301 refactor(BurnPdfCommand): add extension methods for ISender
- Introduce BurnPdfCommandExtensions to simplify sending BurnPdfCommand via ISender
- Enables calling `sender.BurnPdf(envelopeId, cancel)` or `sender.BurnPdf(envelopeUuid, cancel)`
- No changes to the underlying PDF burning logic in BurnPdfCommandHandler
2025-11-10 14:00:21 +01:00
495adb8c31 feat(dependency-injection): add optional usePdfBurner flag to AddServices
- Updated EGConfiguration.AddServices to accept a new `usePdfBurner` boolean parameter.
- Pass `usePdfBurner` through to AddEnvelopeGeneratorServices to enable optional PDF burner functionality.
- Maintains existing behavior when parameter is not provided (default false).
2025-11-10 13:53:26 +01:00
86c0a65540 refactor: add conditional PDFBurner and GdPicture service registration 2025-11-10 13:43:44 +01:00
d2e8f1fc5e refactor: simplify GdPicture license resolution in dependency injection 2025-11-10 13:29:02 +01:00
f8369e350f refactor(BurnPdfCommand): replace manual JSON serialization with ToJson extension
- Replaced `System.Text.Json.JsonSerializer.Serialize(request, Format.Json.ForDiagnostics)`
  with `request.ToJson(Format.Json.ForDiagnostics)` for better readability and consistency.
- No functional changes, purely a code style and maintainability improvement.
2025-11-10 13:01:33 +01:00
b8a2ad97ef refactor(BurnPdfCommand): simplify BurnPdfCommand and improve envelope/document handling
- Updated `BurnPdfCommand` to accept `EnvelopeId` or `EnvelopeUuid` instead of full `EnvelopeQueryBase` and document data.
- Reworked `BurnPdfCommandHandler` to fetch envelope and document from repositories, including proper validations and exceptions.
- Removed direct dependency on `Signature` repository; annotations now retrieved via document elements.
- Added detailed exception handling for missing envelope, document, or byte data.
- Minor namespace and using cleanup.
2025-11-10 12:58:04 +01:00
ffffc2d470 refactor(BurnPdfCommand): update BurnPdfCommand to use EnvelopeQueryBase and enhance request structure
- Replaced record-based BurnPdfCommand with class-based implementation
- Added Envelope property of type EnvelopeQueryBase
- Changed parameters to nullable (Document, InstantJSONList)
- Added ByCronService flag for cron-based PDF burning control
- Updated query logic to use request.Envelope.Id instead of EnvelopeId
- Improved code structure for flexibility and service integration
2025-11-10 09:30:04 +01:00
36b03da084 fix(DependencyInjection): change AnnotationManager registration from Scoped to Transient 2025-11-07 15:21:36 +01:00
defa53fa26 refactor(BurnPdfCommand): rename SourceBuffer to Document in BurnPdfCommand and handler
- Renamed parameter `SourceBuffer` to `Document` in BurnPdfCommand record
- Updated all usages of `request.SourceBuffer` to `request.Document`
- Reorganized method order for better readability (Handle moved up)
- No functional or behavioral changes introduced
2025-11-07 14:56:34 +01:00
6134b58a4c refactor(BurnPdfCommand): extract GdPicture and math helpers into extension classes and simplify BurnPdfCommandHandler
- Refactored BurnPdfCommandHandler to use new extension methods for cleaner annotation handling.
- Introduced ITextStyle interface to generalize font styling for text annotations.
- Updated PDFBurnerParams to implement ITextStyle for consistent font settings reuse.
- Added MathematExtensions for coordinate and unit conversion (ToInches, ToPointF).
- Added GdPictureExtensions to encapsulate annotation-related logic (form fields, images, ink).
- Improved readability and maintainability by removing redundant helper methods.
2025-11-07 14:46:55 +01:00
5299016b43 move PSDPFKitModels namespace to Dto and rename as PSPDFKitInstant 2025-11-07 13:51:53 +01:00
55c20e83d8 refactor: convert BurnPdfCommand to record and update handler to return byte[]
- Changed `BurnPdfCommand` from empty class to a `record` with properties: `SourceBuffer`, `InstantJSONList`, `EnvelopeId`.
- Updated `BurnPdfCommandHandler` to implement `IRequestHandler<BurnPdfCommand, byte[]>`.
- Modified `Handle` method to be async and use the `request` data to return PDF bytes.
- Removed obsolete `BurnPdfCommand` class and updated related logic accordingly.
2025-11-07 13:44:53 +01:00
f1a140faa7 feat(BurnPdfCommandHandler): implement AddInkAnnotation for Annotation parameter
- Added implementation for AddInkAnnotation(Annotation) to handle ink annotations from Annotation objects.
- Retained existing AddInkAnnotation(int, string) method for backward compatibility.
- Refactored PDF burning logic to support both Annotation-based and JSON-based annotations.
2025-11-07 13:24:26 +01:00
b20d25e5b9 feat(BurnPdfCommandHandler): implement AddInkAnnotation for freehand annotations
- Added implementation for AddInkAnnotation(int page, string value) to render ink annotations from JSON.
- Deserialize ink lines and stroke color, convert points to PDF coordinates, and add as freehand annotations.
- Retained placeholder for AddInkAnnotation(Annotation pAnnotation) for future use.
2025-11-07 13:21:33 +01:00
e21eb2c0d6 refactor(BurnPdfCommandHandler): rename AddInstantJSONAnnotationToPdf to AddInstantJsonAnnotationToPdf for consistent casing 2025-11-07 13:16:14 +01:00
d237b4ab95 feat(BurnPdfCommand): implement AddImageAnnotation with attachment handling
- Added logic to AddImageAnnotation to handle image attachments from a dictionary.
- Removed NotImplementedException placeholder for AddImageAnnotation with attachments.
- Refactored code to convert annotation bounds from pixels to inches before adding images.
2025-11-07 13:14:02 +01:00
dff99b163d refactor: simplify AddFormFieldValue method and remove redundant parameters 2025-11-07 13:12:01 +01:00
70fbf31b14 feat(BurnPdfCommandHandler): implement AddImageAnnotation for base64 images
- Added implementation for AddImageAnnotation(double x, double y, double width, double height, int page, string base64)
- Allows embedding images directly from base64 into PDF pages
- Existing annotation burning logic remains unchanged
2025-11-07 13:09:54 +01:00
339e0e81cd feat(PDFBurnerParams): add DefaultIndexOfAnnot and GetAnnotationIndex
- add `DefaultIndexOfAnnot` property to provide a fallback index for annotations
 - add `GetAnnotationIndex(string name)` method to safely retrieve an annotation index, returning default if not found
2025-11-07 13:03:50 +01:00
a386ad72bb refactor(BurnPdfCommandHandler): use IOptions<PDFBurnerParams> and improve form field handling
- Updated BurnPdfCommandHandler constructor to accept IOptions<PDFBurnerParams> instead of raw PDFBurnerParams.
- Updated AddFormFieldValue to calculate coordinates based on PDFBurnerParams offsets and margins.
- Added helper methods for converting pixels to inches (ToInches, ToPointF).
- Removed unused NotImplemented methods in AddFormFieldValue overload.
- Improved code readability and maintainability for annotation burning logic.
2025-11-07 12:59:13 +01:00
02c5f286ec feat(pdf): implement AddFormFieldValue for PDF annotations
- Added implementation for AddFormFieldValue method to properly add text annotations to PDF pages using AnnotationManager.
- Preserves font settings from PDFBurnerParams.
- Other annotation methods remain unimplemented.
2025-11-07 12:44:05 +01:00
5fa358ca79 refactor(BurnPdfCommandHandler): deserialize and process instant JSON annotations
- Added Newtonsoft.Json to parse instant JSON into `InstantData`.
- Replaced `AddInstantJSONAnnotationToPDF` logic with `AddInstantJsonAnnotationToPdf`.
- Process annotations by type (Image, Ink, Widget) and apply attachments/form fields.
- Introduced checks for ignored form field values using `_pdfBurnerParams.IgnoredLabels`.
- Added logging for annotation IDs when processing instant JSON.
2025-11-07 12:36:19 +01:00
7233d2ce98 add InstantData 2025-11-07 11:37:28 +01:00
5784cc7a97 refactor(Application.Pdf.PSPDFKit): rename as Application.Pdf.PSPDFKitModels 2025-11-07 11:28:55 +01:00
f31f680f91 add PSPDFKit.Annotation 2025-11-07 11:27:07 +01:00
e7c2d46ef0 add PSPDFKit.Ink 2025-11-07 11:23:04 +01:00
85d70c1db4 feat(PDFBurnerParams): add IndexOfAnnot-dictionary 2025-11-07 11:16:22 +01:00
fb340fb08a create PSPDFKit.Lines 2025-11-07 10:59:13 +01:00
7d3959ae51 add PSPDFKit.Attachment 2025-11-07 10:56:53 +01:00
9d4890b10d add PSPDFKit.FormFieldValue 2025-11-07 10:52:15 +01:00
b64f4d71f5 feat(BurnPdfCommandHandler): add logging and implement BurnInstantJSONAnnotsToPDF
- Added ILogger<BurnPdfCommandHandler> to log warnings during annotation processing
- Implemented BurnInstantJSONAnnotsToPDF method to handle instant JSON annotations
- Added AddInstantJSONAnnotationToPDF stub for future implementation
- Updated PDF burn flow to include error handling and logging
2025-11-07 10:40:44 +01:00
b7d146ddb5 refactor: standardize annotation types and clean up PDF burn handler
- Introduced `AnnotationType.PSPDFKit` constants for consistent annotation type references.
- Updated `BurnPdfCommandHandler` to use new PSPDFKit annotation types.
- Refactored method signatures and local variables for clarity (e.g., using 'var', null-coalescing for annotation properties).
- Streamlined `using` statements and memory management in PDF burning process.
- Added placeholder methods for form fields, image, and ink annotations to centralize future implementations.
2025-11-07 10:11:48 +01:00
6a5c9a3489 fix(BurnPdfCommand): improve JSON serialization and null safety in Signature entity and BurnPdfCommandHandler
- Added System.Text.Json.Serialization namespace and [JsonIgnore] attributes to Top and Left properties in Signature entity for .NET builds
- Applied null-forgiving operator (!) and null-coalescing defaults for frame.X and frame.Y in BurnPdfCommandHandler
- Improved runtime safety and prevented unintended JSON serialization of computed properties
2025-11-07 09:51:02 +01:00
Developer 02
15f6ee7be0 add ExportDocumentException 2025-11-06 21:53:36 +01:00
Developer 02
1051c5356f add CreateReportException 2025-11-06 21:52:35 +01:00
Developer 02
7b13350fbf add BurnAnnotationException 2025-11-06 21:51:20 +01:00
Developer 02
2bada327d8 add MergeDocumentException 2025-11-06 21:50:17 +01:00
Developer 02
a47729ebca feat(pdf): implement annotation burning logic in BurnPdfCommandHandler
- Added full implementation of BurnElementAnnotsToPDF method
- Integrated PdfEditor for background rendering
- Added annotation handling for form fields, images, and ink types
- Included error handling for PDF loading and saving
- Removed unused DigitalData.Core.Abstractions namespace
2025-11-06 21:49:24 +01:00
Developer 02
fcfed963b7 feat(pdf): add annotation burning logic and repository dependency to BurnPdfCommandHandler
- Inject IRepository<Signature> for accessing signature and annotation data
- Implement BurnAnnotsToPDF method to process annotations from DB or JSON
- Add BurnElementAnnotsToPDF and BurnInstantJSONAnnotsToPDF stubs
- Integrate EF Core Include for loading related entities
2025-11-06 21:30:51 +01:00
Developer 02
b2ace61cd4 refactor(BurnPdfCommandHandler): inject AnnotationManager 2025-11-06 21:20:57 +01:00
Developer 02
77cdc83a4e add AnnotationManager as scoped 2025-11-06 21:19:05 +01:00
Developer 02
a611df4914 inject LicenseManager 2025-11-06 21:09:46 +01:00
Developer 02
1341f69ab1 move gdpucture parmas configuration to application layer 2025-11-06 20:57:10 +01:00
Developer 02
0480513288 add gdpicture dependencies 2025-11-06 20:10:41 +01:00
Developer 02
9dbd1b16b5 inject pdf burner params 2025-11-06 19:57:56 +01:00
Developer 02
c649c93921 move pdf burner to application layer 2025-11-06 19:51:15 +01:00
Developer 02
1843119b1b add PDFBurnerParams 2025-11-06 19:39:43 +01:00
Developer 02
bc4371cb99 feat(PDFBurner): init for only .net 2025-11-06 19:34:39 +01:00
Developer 02
05130d6163 feat(FinishEnvelopeJob): enhance FinishEnvelopeJob logging for finalized envelopes
- Removed redundant initial info log.
- Added detailed logging after job execution:
  - Logs total finalized envelope count.
  - Logs UUIDs of finalized envelopes when available.
  - Logs success message when no envelopes were finalized.
2025-11-06 09:59:16 +01:00
567b9c9565 refactor(Envelope): remove unnecessary [NotMapped] attribute from DocResult property 2025-11-05 16:49:39 +01:00
b798181f91 feat(notification): implement handler to remove document result on signature removal 2025-11-05 15:26:48 +01:00
7e8fc25ec9 refactor: update core inf and abst.app 2025-11-05 14:31:24 +01:00
db76162697 Refactor: Convert envelope query filters to LINQ query syntax
- Replaced multiple sequential 'Where' calls with a single LINQ query expression
- Preserved all status filters (Include, Ignore, Min, Max)
- Preserved DocResult filtering logic
- Improves readability while keeping behavior identical
2025-11-05 13:39:10 +01:00
2b4573ea73 feat(ReadEnvelopeQuery): implement ReadEnvelopeQueryHandler with filtering support
- Added `ReadEnvelopeQueryHandler` to handle `ReadEnvelopeQuery`.
- Supports filtering envelopes by:
  - Included and ignored `EnvelopeStatus` values.
  - Minimum and maximum status.
  - Presence or absence of `DocResult`.
- Uses repository query extension methods and AutoMapper to map to `EnvelopeDto`.
2025-11-05 13:32:30 +01:00
4a043ed247 feat(FinishEnvelopeJob): update Execute to add cancelation token 2025-11-05 12:58:35 +01:00
a62a035ec6 feat(FinishEnvelopeJob): enhance FinishEnvelopeJob to fetch signed envelopes
- Added MediatR dependency to query envelopes
- Injected GdPictureOptions via IOptions
- Updated Execute method to fetch envelopes with status 'EnvelopeCompletelySigned'
- Preserved logging with job details
- Prepared loop for further processing of envelopes
2025-11-05 12:55:49 +01:00
1713a65014 refactor(Program): simplify Quartz job registration and add EnvelopeTaskApiJob
- Replaced manual FinishEnvelopeJob Quartz setup with ScheduleJobDefault extension
- Added scheduling for EnvelopeTaskApiJob
- Updated using directives to include EnvelopeGenerator.Finalizer namespace
- Improved maintainability by removing redundant Quartz configuration logic
2025-11-05 11:24:35 +01:00
695d7c83e0 feat(Extensions): add Quartz job scheduling extension methods
- Introduced ScheduleJobDefault<TJob> extension for IServiceCollectionQuartzConfigurator
- Allows scheduling jobs using either a cron expression or configuration-based cron settings
- Includes validation for missing or invalid cron expressions
2025-11-05 10:43:25 +01:00
428f71863d create EnvelopeTaskApi 2025-11-05 09:41:02 +01:00
cce2f8f90e refactor(Worker): rename as FinishEnvelopeJob 2025-11-05 09:34:56 +01:00
Developer 02
86c9fdfcd7 refactor: inject IScheduler via DI instead of using StdSchedulerFactory directly 2025-11-04 17:34:36 +01:00
Developer 02
89ec887510 feat(quartz): integrate Quartzmon dashboard and CommandDotNet
- Added `Quartzmon` package and configured its middleware for job monitoring.
- Integrated `CommandDotNet.Execution` for command-line execution support.
- Updated using directives and service registrations accordingly.
- Preserved existing Serilog logging, DB context, and EnvelopeGenerator setup.
2025-11-04 17:29:07 +01:00
Developer 02
7d5b988842 fix(middleware): add UseRouting before UseAuthorization
Added `app.UseRouting()` in the middleware pipeline to ensure proper endpoint routing before authorization and controller mapping.
2025-11-04 17:18:29 +01:00
Developer 02
3c456562cc refactor: replace QuartzHostedService with QuartzServer and remove unnecessary using
- Replaced `AddQuartzHostedService` with `AddQuartzServer` for better Quartz integration.
- Removed `Microsoft.Extensions.Options` using as it was unused.
- Updated Quartz job naming to remove GUID and simplify identity.
- Minor code cleanup in using statements and regions.
2025-11-04 17:06:00 +01:00
Developer 02
4d6b01030c refactor(startup): migrate from generic Host to WebApplication and integrate Web API support
- Replaced Host.CreateApplicationBuilder with WebApplication.CreateBuilder
- Added Web API service registrations (Controllers, Swagger)
- Organized startup into clear regions: Logging, Configuration, Worker, Services, Middleware
- Introduced Swagger and HTTPS middleware for API
- Improved structure and readability of Program.cs
2025-11-04 16:12:21 +01:00
Developer 02
75e7e9925b feat(Program): make Quartz cron schedule configurable via appsettings
- Replaced hardcoded cron expression with configuration-based `Worker:CronExpression`.
- Throws descriptive exception if cron expression is missing.
- Keeps previous worker and DB context setup unchanged.
2025-11-04 15:37:20 +01:00
Developer 02
0a175b9e9d refactor: remove unnecessary while loop in Worker.Execute 2025-11-04 15:18:38 +01:00
Developer 02
f611e74de1 refactor(config): allow GdPicture license key from configuration
- Updated GdPictureOptions setup to read license key from `GdPictureLicenseKey` config value.
- Falls back to reading from third-party module if config key is not set.
2025-11-04 14:56:44 +01:00
Developer 02
08ca116628 refactor(worker): replace BackgroundService with Quartz IJob for scheduled execution
- Removed inheritance from BackgroundService
- Implemented Quartz IJob interface for better scheduling control
- Replaced ExecuteAsync with Execute(IJobExecutionContext)
- Updated cancellation handling to use context.CancellationToken
2025-11-04 14:49:56 +01:00
Developer 02
4997f7d75c feat: add in-memory database support via appsettings UseInMemoryDb flag
- Introduced conditional EF Core configuration to support InMemoryDatabase for testing or lightweight runs.
- Added `UseInMemoryDb` config flag read from appsettings.
- Retained SQL Server as the default when the flag is false.
- Added missing Quartz namespace import.
2025-11-04 13:44:39 +01:00
b5cd42b6fa add WorkerOptions.
- bind IntervalInMin with worker task delay
2025-11-03 16:38:41 +01:00
187f4a42fc feat(GdPictureOptions): Created to configure parameters related to GdPicture.
- Configure the GdPicture license key via a third-party module entity.
2025-11-03 15:36:11 +01:00
23d4b2f31e chore: move finalizer to presentation layer 2025-11-03 14:51:13 +01:00
8e71e5b4bb feat(third-party-modules): add query and handler for reading third-party modules with filtering by name and active status 2025-11-03 14:49:54 +01:00
b693615561 feat(ThirdPartyModuleDto): create DTO of ThirdPartyModule with mapping profile 2025-11-03 14:30:45 +01:00
36dc9266bc Add ThirdPartyModule entity for 3rd party module tracking
- Created ThirdPartyModule class in EnvelopeGenerator.Domain.Entities
- Mapped to TBDD_3RD_PARTY_MODULES table with appropriate columns
- Added properties: Id, Active, Name, Description, License, Version, AddedWho, AddedWhen, ChangedWho, ChangedWhen
- Configured data annotations for primary key, required fields, string lengths, and nullable support
- Conditional nullable support based on compilation symbols
2025-11-03 13:05:24 +01:00
9aabe270b4 add appsettings for PDF burner 2025-11-03 11:56:10 +01:00
b303b7be06 chore(Finalizer.Program): enhance configuration and environment-specific JSON loading
- Changed Serilog configuration file from `appsettings.json` to `appsettings.Logging.json`.
- Added logging for application startup.
- Dynamically load environment-specific appsettings JSON files, excluding `Development` and `migration` files.
2025-11-03 11:41:55 +01:00
02937360ea chore(Finalizer.appsettings): update Serilog configuration to increase log verbosity and retention
- Changed default minimum log level from Information to Verbose.
- Updated console sink to use Verbose level.
- Renamed and consolidated log files for Verbose, Debug, Info, Warning, Error, and Fatal levels.
- Increased retained file count from 7 to 30 for all log levels.
2025-11-03 11:26:14 +01:00
c2735b92e0 feat(logging): enhance Serilog configuration with separate level-based log files 2025-11-03 10:48:35 +01:00
568f43186c refactor(Finalizer.Program): simplify EnvelopeGenerator service registration using AddEnvelopeGenerator extension
- Replaced manual service setup with AddEnvelopeGenerator fluent configuration
- Added EnvelopeGenerator.DependencyInjection namespace
- Integrated distributed SQL Server cache for EG services
- Improved DI structure and reduced obsolete warnings
2025-11-03 10:24:09 +01:00
3bc5439b5a feat(dependency-injection): add service configuration validation and simplify setup
- Removed unnecessary IConfiguration and SqlServerCacheOptions parameters from AddEnvelopeGenerator
- Added EnsureAllServicesConfigured() to validate that all required service methods are invoked
- Introduced _addingStatus dictionary to track configuration status
- Renamed internal queue field to _serviceRegs for consistency
- Added AddServices() method to explicitly register EnvelopeGenerator services
- Improved AddLocalization() to support optional custom localization options
2025-11-03 09:30:43 +01:00
22b494a262 refactor(di): unify Application and Infrastructure DI registrations under a central method
- Added central AddEnvelopeGenerator extension to aggregate existing DI setups
- Introduced EGConfiguration for modular service registration
- Standardized configuration pattern for Application and Infrastructure layers
- Simplified distributed cache and localization registration
2025-11-03 08:44:22 +01:00
209785dda5 refactor(DependencyInjection): created to handle DependencyInjection 2025-10-31 11:31:39 +01:00
44ea893f05 move memory-cache injection to Application-layer 2025-10-31 10:58:22 +01:00
b4aa7984aa chore(Application): Update your packages with vulnerabilities
- Added `SixLabors.ImageSharp` (v3.1.12) to main package references.
- Added `System.Formats.Asn1` for all target frameworks:
  - net7.0 → v8.0.2
  - net8.0, net9.0 → v9.0.10
2025-10-31 10:34:25 +01:00
7c5a505ad1 add serilog 2025-10-31 10:23:11 +01:00
bd6d57e1e8 feat: integrate EnvelopeGenerator infrastructure, DB context, and services
- Added references to EnvelopeGenerator.Application, Infrastructure, and EF Core.
- Configured DB context with SQL Server connection string from configuration.
- Registered EnvelopeGenerator services and infrastructure with dependency injection.
- Preserved warnings suppression for obsolete members.
- Structured DI registration under a dedicated region for clarity.
2025-10-30 17:05:45 +01:00
8403ce2c6a init EnvelopeGenerator.Finalizer 2025-10-30 16:31:22 +01:00
c3deaae63b refactor(Service): add UserConfig 2025-10-30 14:39:15 +01:00
bb0197e6ba refactor: wrap repository access in a DI scope in PDFBurner
- Updated `BurnAnnotsToPDF` to create a scope using `Factory.Shared.ScopeFactory.CreateScope()`
  before accessing the `Signature` repository.
- Ensures proper disposal of services and improves dependency injection usage.
- No functional changes to PDF burning logic.
2025-10-29 17:40:42 +01:00
ec2935b524 refactor: update EnvelopeGenerator factory initialization with PostBuildBehavior 2025-10-29 17:14:49 +01:00
4fd7982cba refactor: update EnvelopeGenerator infrastructure service initialization
- Added `BehaveOnPostBuild(PostBuildBehavior.Ignore)` in the Factory initialization
- Adjusted formatting for better readability of `AddEnvelopeGeneratorInfrastructureServices` call
- No functional changes to job execution or PDF/email processing
2025-10-29 17:01:24 +01:00
ddcf5edc00 update DigitalData.Core.Abstractions 2025-10-29 16:54:12 +01:00
74d207caa3 refactor(EnvelopeGenerator.Service): update Microsoft.Extensions.Logging.Abstractions to 7.0.0 2025-10-29 16:29:07 +01:00
a367c12551 chore(Web): bump to 3.5 2025-10-28 16:57:20 +01:00
35a328f8dc feat(pdfburner): adjust background rendering in BurnElementAnnotsToPDF
- Added scaling factors (1.95 * 0.93, 2.52 * 0.67) to the background generation step
- Included TODO note to calculate length dynamically based on largest Y value
- Improved visual accuracy of PDF background rendering for element annotations
2025-10-28 16:56:00 +01:00
d259a15b4b refactor: add DigitalData.Core.Abstractions.Interfaces import and make Background method width/height configurable 2025-10-28 16:43:59 +01:00
23e0e5ddbe fix(pdfburner): correct annotation X-coordinate handling in BurnElementAnnotsToPDF
Adjusted logic in `BurnElementAnnotsToPDF` to properly use annotation X position
(`annot.X / inchFactor`) instead of offset-based calculation with `frameX` and
`frameXShift`. This ensures more accurate placement of form fields and images
when burning annotations into PDFs.
2025-10-28 16:40:06 +01:00
0bb85c28c1 fix: adjust annotation position calculation in PDFBurner
- Updated BurnElementAnnotsToPDF method to correctly align image annotations relative to the frame position.
- Introduced frame-based coordinate shifting (frameXShift and frameYShift) to handle signature positioning accurately.
- Replaced variable `x` with `frameX` for better clarity and consistency.
2025-10-28 16:27:55 +01:00
a11d9a0e0e refactor(PDFBurner): adjust annotation positioning and unit conversions in PDFBurner
- Renamed variable `magin` → `margin` for clarity
- Revised coordinate calculations for annotation positioning (`x`, `y`)
- Adjusted width and height units to use inches instead of fixed inchFactor multipliers
- Updated y-offset logic for form fields (`yOffsetsOfFF`) to improve layout alignment
- Simplified image annotation scaling (removed division by 100)
- Improved code readability and comment consistency
2025-10-28 15:27:52 +01:00
b9bb058137 fix(AnnotationCreateDto): rename WIDTH and HEIGHT properties to Width and Height in AnnotationCreateDto 2025-10-28 14:42:14 +01:00
0818d7d9eb feat(dto): add position and size properties to AnnotationCreateDto 2025-10-28 14:14:09 +01:00
9d200800c5 feat: add position and size properties to ElementAnnotation entity
- Added `X`, `Y`, `Width`, and `Height` properties with `float` database mapping.
- Retains existing fields and database annotations.
- Prepares the entity for spatial layout handling in documents.
2025-10-28 14:10:32 +01:00
6feb601670 fix(annotations): include bounding box coordinates in mapped signature and frame data
- Added extraction of `x`, `y`, `width`, and `height` from annotations and frames in `mapSignature`.
- Ensures positional data is correctly preserved when mapping signatures and frames from PSPDFKit annotations.
- No functional changes to annotation creation, deletion, or validation.
2025-10-28 13:58:03 +01:00
39c12ada45 refactor(annotations): include bounding box info in mapped signature fields
- Added `x`, `y`, `width`, and `height` properties to form field mapping in `mapSignature`.
- Preserves original form field values while enriching them with annotation coordinates.
- No functional changes to annotation creation, deletion, or validation.
2025-10-28 13:49:26 +01:00
985ad4dc29 fix(pdf-burner): correct image annotation type and scaling
- Fixed conditional check in BurnElementAnnotsToPDF to correctly handle AnnotationType.Image.
- Adjusted AddImageAnnotation method to scale width and height by dividing by 100.
- No functional changes to other PDF burning or annotation logic.
2025-10-28 13:00:43 +01:00
038ac2aed0 fix(annotations): correct signature frame mapping by filtering by pageIndex
- Updated `mapSignature` to filter signature annotations by `pageIndex` when finding nearest elements.
- Ensures correct association of frames and signature data for each page.
- Prevents errors caused by cross-page annotation references.
2025-10-28 12:59:49 +01:00
5e74de0ce7 refactor(pdf-burner): adjust annotation positioning logic in BurnElementAnnotsToPDF
- Introduced configurable inch factor, margins, width, and height for annotations
- Added dynamic Y-offsets for form fields based on annotation names
- Simplified AddFormFieldValue logic for direct coordinates
- Removed hardcoded offsets previously embedded in the method
2025-10-28 11:48:19 +01:00
0ce7ae9494 fix(pdfburner): correct page indexing for annotation rendering
- Removed unnecessary +1 offset in Manager.SelectPage calls for image and ink annotations
- Ensured correct page index is used when adding annotations and form field values
- Improved annotation rendering accuracy when burning to PDF
2025-10-28 10:48:15 +01:00
7041a4694a fix: ensure annotations are properly burned after background addition in PDFBurner 2025-10-28 10:43:19 +01:00
75e47d10e3 feat(pdfburner): add ink annotation support and refactor annotation handling
- Added new AddInkAnnotation(page As Integer, value As String) method to handle ink annotations from element data.
- Introduced new Ink model class for deserializing ink annotation data (lines and strokeColor).
- Updated BurnElementAnnotsToPDF to support Ink annotation type.
- Refactored annotation type handling for better extensibility.
- Improved annotation burning logic for mixed annotation types (form fields, images, inks).
2025-10-28 10:06:38 +01:00
7f9125b3aa refactor: add AddImageAnnotation-method 2025-10-28 09:43:43 +01:00
fee256a51a add y offset to AddFormFieldValue metot 2025-10-28 09:25:48 +01:00
8ad7c37261 refactor(PdfBurner): update BurnAnnotsToPDF to add form field 2025-10-28 09:09:53 +01:00
ef28bbaaf1 refactor(pdf-burner): replace annotation type constants with AnnotationType class
- Removed individual annotation type constants (ANNOTATION_TYPE_IMAGE, ANNOTATION_TYPE_INK, ANNOTATION_TYPE_WIDGET)
- Introduced new Friend Class `AnnotationType` to encapsulate annotation type string constants
- Updated all references to use `AnnotationType.Image`, `AnnotationType.Ink`, and `AnnotationType.Widget`
- Improved code organization by grouping related constants and removing redundant declarations
2025-10-24 13:50:24 +02:00
258de6244c refactor(pdf-burner): organize code with regions for better readability
- Grouped related methods and classes into logical #Region blocks:
  - "Burn PDF"
  - "Add Value"
  - "Helpers"
  - "Model"
- Improved code structure and readability without changing functionality.
- No logic or behavior modifications were made.
2025-10-24 12:30:16 +02:00
a845b85a5c refactor(PDFBurner): separate element annotation burning into dedicated method and simplify BurnAnnotsToPDF logic 2025-10-24 12:21:04 +02:00
02a7b706cf refactor(PDFBurner): extract instant JSON annotation burning logic into separate method
- Moved annotation burning logic from `BurnAnnotsToPDF` into new method `BurnInstantJSONAnnotsToPDF`
- Simplified `BurnAnnotsToPDF` to handle only background generation and call the new method
- Improved code readability and separation of concerns
2025-10-23 17:05:37 +02:00
7912469709 refactor(pdf): add output stream disposal management to Pdf class
- Added `disposeOutputStream` parameter to Pdf constructor
- Updated `FromMemory` to set output stream disposal based on null value
- Ensured proper cleanup of output stream in Dispose and DisposeAsync methods
- Improved resource management to prevent potential memory leaks
2025-10-23 14:34:57 +02:00
75d975223e feat(pdf): add optional output stream parameter to FromMemory overload
- Updated Pdf.FromMemory(MemoryStream) to accept an optional outputStream parameter
- Ensures flexibility when reusing existing MemoryStreams for output
- Added conditional nullability support for .NET builds
2025-10-23 14:30:30 +02:00
c456d67d03 feat(pdf): add option to preserve input stream on disposal
- Introduced `disposeInputStream` parameter in `Pdf<TInputStream, TOutputStream>` constructor.
- Updated `Dispose` and `DisposeAsync` to conditionally dispose the input stream based on this flag.
- Updated `Pdf.FromMemory(MemoryStream)` to not dispose the provided MemoryStream by default.
- Ensures better control over resource management when reusing input streams.
2025-10-23 13:51:40 +02:00
241e59fc7e feat(Pdf): add FromMemory method to be able to create via stream 2025-10-23 13:39:59 +02:00
f0d101bb23 refactor(pdf-burner): rename BurnInstantJSONAnnotationsToPDF to BurnAnnotsToPDF
- Updated method name to better reflect its functionality.
- No changes to logic or behavior; purely a rename for clarity.
2025-10-23 13:36:32 +02:00
8db5afae40 feat(PDFBurner): add background rendering using PdfEditor before burning annotations 2025-10-23 12:54:53 +02:00
b62cca5961 feat(pdf-burner): integrate repository to fetch envelope annotations
- Added repository access to retrieve signatures and their annotations for a given envelope.
- Updated `BurnInstantJSONAnnotationsToPDF` to accept `envelopeId` and load elements from the database.
- Updated imports to include `DigitalData.Core.Abstractions` and Entity Framework references.
2025-10-23 12:14:35 +02:00
0e7b120ded refactor(Entities.Annotation): rename it to ElementAnnotation to prevent name conflicts. 2025-10-23 10:51:19 +02:00
d8cbdb0c65 chore:
- upg Core.Abstraction.Application to 1.4.0
 - upg Core.Abstractions to 4.2.0
2025-10-23 10:37:15 +02:00
0107602a84 upg Abstraction.Application and Application projects 2025-10-22 18:34:40 +02:00
02ecd88758 feat(TestAnnotationController): include receiver signature in RemoveSignatureNotification
Updated TestAnnotationController.Delete to extract the receiver signature from the envelope key
and pass it along with the envelope UUID when publishing RemoveSignatureNotification.
Returns BadRequest if the signature is missing.
2025-10-22 14:29:38 +02:00
17c7e46388 fix(AnnotationController): use PublishSafely for docSignedNotification
Replaced `await _mediator.Publish(docSignedNotification, cancel)` with
`await _mediator.PublishSafely(docSignedNotification, cancel)` to ensure
safe publishing of notifications without unhandled exceptions.
2025-10-22 14:25:50 +02:00
f3af30c67d feat(DocSignedNotificationExtensions): add PublishSafely extension for DocSignedNotification
- Introduced PublishSafely method to safely publish DocSignedNotification events.
- Added fallback logic to publish RemoveSignatureNotification when publishing fails.
- Added missing using directive for RemoveSignatureNotification namespace.
2025-10-22 13:10:38 +02:00
90e10d3d04 refactor(RemoveSignatureNotification): update handlers to throw exception if there is no filter 2025-10-22 12:50:57 +02:00
af14ef7ce5 feat(RemoveSignatureNotification): add validation and filter logic to RemoveSignatureNotification
- Added `HasFilter` property to check if any filter parameters are provided.
- Implemented `ThrowIfHasNoFilter()` method to enforce at least one filter parameter.
- Improves robustness and validation of RemoveSignatureNotification.
2025-10-22 11:02:10 +02:00
1edcfed318 refactor(RemoveSignatureNotification): Alle Filter von Handlern an die Bedingung binden, dass sie nicht null sind. 2025-10-22 10:38:08 +02:00
2004c7ced2 feat(RemoveSignatureNotification): extend RemoveSignatureNotification with EnvelopeId and ReceiverId
Added optional parameters `EnvelopeId` and `ReceiverId` to RemoveSignatureNotification
to provide additional context when removing receiver signatures.
2025-10-21 16:43:01 +02:00
40135fb8a2 feat(RemoveHistoryHandler): add filtering by receiver signature in RemoveHistoryHandler
Added logic to filter history records by receiver signature when provided in
RemoveSignatureNotification. This ensures only relevant signed entries are deleted.
2025-10-21 15:51:55 +02:00
b57c0aa9c7 refactor(RemoveDocStatusHandler): update RemoveDocStatusHandler to support conditional receiver signature filtering
Updated the RemoveDocStatusHandler to refine document status deletion logic.
Now filters by EnvelopeUuid and optionally by ReceiverSignature when provided.
2025-10-21 15:41:09 +02:00
2c4c18935f feat(RemoveSignatureNotification): add ReceiverSignature to RemoveSignatureNotification
Added a new nullable ReceiverSignature property to the RemoveSignatureNotification record
to support handling receiver-specific signature removal events.
2025-10-21 15:25:04 +02:00
d8ed06fdb6 feat(RemoveAnnotationHandler): add RemoveAnnotationHandler to handle signature removal notifications
- Implements INotificationHandler<RemoveSignatureNotification>
- Deletes Annotation entities matching the Envelope UUID from the repository
- Uses IRepository<Annotation> for data access
2025-10-21 12:43:59 +02:00
09bf8db884 refactor(RemoveAnnotationHandler): rename as RemoveDocStatusHandler 2025-10-21 12:27:54 +02:00
911c812b19 refactor(Annotation): change Id column type from int to bigint in Annotation entity 2025-10-21 11:45:23 +02:00
8ae0f79365 refactor(AnnotationDto): split AnnotationDto into AnnotationCreateDto and AnnotationDto
- Introduced AnnotationCreateDto for creation-specific properties
- AnnotationDto now inherits from AnnotationCreateDto and includes Id, AddedWhen, ChangedWhen, and ChangedWho
- Added Type property to AnnotationCreateDto
 - remove CreateAnnotationCommand
2025-10-21 11:42:01 +02:00
0ca54fe1fe feat(DocSignedNotification): replace Annotations with PsPdfKitAnnotation in DocSignedNotification
- Introduced new record `PsPdfKitAnnotation` to encapsulate both Instant and Structured annotation data
- Updated `DocSignedNotification` to use `PsPdfKitAnnotation` instead of `ExpandoObject Annotations`
- Modified extension methods to accept and map `PsPdfKitAnnotation`
- Added reference to `EnvelopeGenerator.Application.Annotations.Commands` for `CreateAnnotationCommand`
2025-10-21 10:11:36 +02:00
a1d6b5347f refactor(annotation): simplify mapSignature function to return a flat array
Reworked mapSignature to return a single flattened array combining formFields,
frames, and signatures instead of a nested object. This simplifies downstream
processing and improves readability.
2025-10-21 09:48:06 +02:00
6cc631111c refactor(annotation): simplify field mapping and return structured objects
Refactored the mapSignature function to:
- Return cleaner structured objects for formFields, frames, and signatures
- Include `type` and `value` properties in returned objects
- Remove direct mutation of field and annotation objects
- Improve readability and maintainability of data mapping logic
2025-10-21 09:38:47 +02:00
9d6074874f fix(annotation): correctly assign elementId for signature annotations
Previously, signature annotations did not include elementId mapping logic, which caused issues when linking annotations to their corresponding elements. This update adds logic to extract elementId from the nearest signature annotation (similar to frame annotations) to ensure proper association.
2025-10-21 09:25:01 +02:00
26bdb0806d feat(MappingProfile): add AutoMapper profile for CreateAnnotationCommand to Annotation 2025-10-21 09:09:56 +02:00
7919f02ffd feat(annotation): enhance mapSignature to support drawn signatures
- Added support for mapping drawn (non-image) signatures by including `lines` and `strokeColor` data.
- Added error handling for incompatible or missing signature data structures.
- Ensures compatibility with third-party annotation libraries that return vector-based signatures.
2025-10-20 16:35:53 +02:00
04ae14c660 refactor(annotation): update mapSignature to handle frames and signatures separately
- Modified `mapSignature` to set `name` as 'frame' for FRAME annotations and 'signature' for signature annotations.
- Added processing for annotations with `isSignature` to include their `value` from attachments if present.
- Ensures consistent mapping of form fields, frames, and signatures.
2025-10-20 14:29:39 +02:00
cff79730b0 fix(annotations): correctly decode base64 for FRAME annotations
Updated `mapSignature` function to use `fixBase64` when assigning `value`
to FRAME annotations. This ensures any escaped Base64 strings in attachments
are properly converted to standard Base64 format.
2025-10-20 14:22:19 +02:00
188cb67306 feat(annotations): add fixBase64 and map FRAME annotations to nearest signature
- Added `fixBase64` utility to unescape Base64 strings.
- Updated `mapSignature` to link FRAME annotations to their nearest signature element and include `elementId`.
- Ensures proper mapping of annotation frames and consistent data structure for form fields.
2025-10-20 14:05:11 +02:00
abaa315b24 feat(utils): add findNearest function to calculate closest point 2025-10-20 13:40:38 +02:00
4f463c27e6 feat(annotation): extend mapSignature to include FRAME annotations
- Updated `mapSignature` function to also map image/frame annotations.
- For each annotation with `description === 'FRAME'`, add `name` and `value` based on corresponding attachment.
- Preserves existing mapping of form fields, filtering out labels.
- Ensures signature data and associated frames are returned in a structured object.
2025-10-20 11:28:05 +02:00
d6f17ec4e8 feat(annotations): add mapSignature function for mapping form field data
- Introduced new function `mapSignature(iJSON)` to process formFieldValues
- Filters out label fields and maps form field data to include elementId and simplified name
- Enhances annotation handling for signature mapping
2025-10-20 10:59:57 +02:00
e3e2831da1 feat(Annotation): add Type property to Annotation entity and update CHANGED_WHO column type
- Added new required `Type` field with nvarchar(50) to `Annotation` entity.
- Updated `CHANGED_WHO` column type from nchar(100) to nvarchar(50).
- Corresponding database migration required.
2025-10-20 10:37:29 +02:00
52306d481f refactor(app): simplify annotation creation and improve signature handling
- Updated `createImageAnnotation` to use pre-generated id instead of multiple parameters
- Replaced hardcoded annotation ID generation during signature creation
- Added `fixBase64` helper to handle escaped base64 strings
- Temporarily added logging in `handleFinish` for debugging exported InstantJSON
- Simplified `createImageAnnotation` signature and usage
- Improved readability and consistency in annotation ID generation logic
2025-10-17 13:46:07 +02:00
f046be240b refactor(annotations): replace global element index with element.id in generateId
- Removed global __elementIndex counter and updated generateId() to use element.id for unique annotation IDs.
- Updated createAnnotations() and createImageAnnotation() to pass element.id to generateId().
- Simplified ID generation logic for better consistency and traceability across annotations.
2025-10-17 09:33:58 +02:00
16e5d5c692 feat(AnnotationHandler): add handler for DocSignedNotification to create annotations
- Implemented AnnotationHandler to process DocSignedNotification events
- Sends CreateAnnotationCommand via MediatR with envelope, receiver, and annotations data
2025-10-16 14:28:25 +02:00
e64ad44b71 refactor(annotation): simplify PSPDFKitInstantJSON deserialization in CreateAnnotationCommand
Refactored CreateAnnotationCommand to remove the lazy initialization pattern
and replaced it with a direct property setter for PSPDFKitInstantJSON.
This simplifies JSON deserialization and removes unnecessary complexity
in managing the PSPDFKitInstant object.
2025-10-16 11:24:23 +02:00
e88bd55198 refactor(AnnotationHandler): rename as DocStatusHandler 2025-10-16 10:18:32 +02:00
4abed0e1bc fix(data): define navigation property for Envelope–Document relationship
Explicitly specify the navigation property `d.Envelope` in the relationship
between Envelope and Document to ensure proper entity mapping and navigation
in EF Core.
2025-10-15 18:23:43 +02:00
69821e64c6 refactor(Document): update Document entity structure and file properties
- Moved file-related properties (Filename, Filepath, FileNameOriginal) into dedicated region
- Added column mappings for file-related properties
- Changed Elements type to IEnumerable<Signature> for better abstraction
- Adjusted EnvelopeId default initialization for NETFRAMEWORK only
- Updated ByteData and nullable types for NET compatibility
- Removed obsolete default value and simplified property definitions
2025-10-14 10:53:19 +02:00
f13a2434f7 refactor(CreateAnnotationCommand): make JsonSerializerOptions static. 2025-10-14 09:34:59 +02:00
ecc7552951 refactor: move CreateAnnotationCommand extension to separate static class 2025-10-13 17:15:00 +02:00
d10f19d92a refactor(annotation): add lazy JSON deserialization for PSPDFKitInstantJSON
- Introduced Lazy<dynamic> field for deferred deserialization of PSPDFKitInstantJSON
- Added ExpandoObject property (PSPDFKitInstant) for dynamic access
- Updated handler to use ParsePSPDFKitInstant instead of ParsePSPDFKitInstantJSON
- Improved JsonSerializerOptions for case-insensitive property handling
2025-10-13 16:56:00 +02:00
5e53f2b691 refactor(CreateAnnotationCommand): update to return IEnumerable<Signature> as result 2025-10-13 15:51:53 +02:00
f56928f44f feat(CreateAnnotationCommand): implement CreateAnnotationCommand and handler logic
Added full implementation for CreateAnnotationCommand and its handler:
- Introduced `PSPDFKitInstantJSON` property to the command
- Injected repositories for `Signature` and `Annotation`
- Implemented query filtering for Envelope and Receiver
- Added annotation creation from parsed PSPDFKit JSON
- Created helper method `ParsePSPDFKitInstantJSON` for JSON parsing
2025-10-13 15:28:38 +02:00
faa37e0dcd add CreateAnnotationCommandHandler without implementation 2025-10-13 11:17:50 +02:00
e51470a449 create AnnotationDto 2025-10-13 11:16:37 +02:00
adce61fead feat: add CreateAnnotationCommand record for annotation creation 2025-10-13 10:59:58 +02:00
e052bf56f4 feat(EGDbContext): add annotations mapping and clean up constructor initialization
- Added model configuration for Signature → Annotation relationship
- Removed redundant DbSet initializations from EGDbContextBase constructor
- Updated Config DbSet type from Domain.Entities.Config to Config
- Simplified using directives and removed unnecessary configuration imports
- Maintained existing trigger registration and entity configurations
2025-10-13 10:02:26 +02:00
22a7619627 feat(Signature): add Annotations navigation property to Signature entity
- Added `IEnumerable<Annotation>? Annotations` to Signature class
- Added `using System.Collections.Generic;` for .NET Framework builds
2025-10-13 09:48:24 +02:00
281cf47834 refactor(Annotation): rename Guid as Id
- convert type to long
2025-10-13 09:43:08 +02:00
a258dcdad0 feat(Annotation): add Annotation entity for document receiver element annotations
- Added Annotation entity mapped to table TBSIG_DOCUMENT_RECEIVER_ELEMENT_ANNOTATION
- Included data annotations for key, required fields, and relationships
- Added conditional compilation for .NET and .NET Framework compatibility
2025-10-13 09:40:41 +02:00
79c26eb5b5 refactor(PDFBurner): replace fieldName with egName and simplify form field handling
- Removed formFieldIndex tracking and inline dictionary
- Introduced EGName class with centralized index mapping
- Updated AddFormFieldValue to resolve Y-offset using EGName.Index
- Replaced fieldName property with egName for annotations
- Changed helper methods from Function(Void) to Sub for clarity
2025-10-10 15:00:04 +02:00
ce7ca39c39 add isLabel property 2025-10-09 17:42:34 +02:00
7b6f916486 refactor(PDFBurner): rename Annotation.internalType to fieldName for clarity 2025-10-09 12:19:19 +02:00
57422a481c feat(PDFBurner): support unstructured annotations and simplify processing
- Added `UnstructuredAnnotations` property to handle annotations without structured IDs
- Changed default `hasStructuredID` to `False`, set to `True` only after successful parsing
- Updated `AddInstantJSONAnnotationToPDF` to process annotations directly instead of grouping by receiver
- Simplified logic for reversing annotations and applying seal positioning
2025-10-08 16:27:28 +02:00
e96523b786 update to use IRepository<T> 2025-10-08 13:36:09 +02:00
3b7d0e1321 refactor(RemoveSignatureNotification): create with handlers to remove signatures of a document 2025-10-08 12:41:14 +02:00
9adc1ea4e7 refactor(annotation): remove unnecessary loop 2025-10-08 10:26:25 +02:00
510f5e9ddd fix: update to set to hold the value of id in a varable to be able to use form fields 2025-10-08 00:47:17 +02:00
44b204ca68 add structred id to image annotations 2025-10-08 00:36:20 +02:00
b72ac68daf refactor(annotations.js): move generateId method to outsite of createAnnotations method 2025-10-08 00:29:37 +02:00
7d85d59ace add hasStructuredID property isntead of throwing exception and filter it 2025-10-08 00:19:28 +02:00
4fad41bd0b update to use # as seperator instead of _ 2025-10-07 22:19:01 +02:00
39936792aa update to use annotations-by-receiver for iteration 2025-10-07 22:16:52 +02:00
74f444a8d6 feat(PDFBurner): add AnnotationsByReceiver method to AnnotationData 2025-10-07 21:54:18 +02:00
b67f26cc21 refactor(PDFBurner): enhance annotation ID handling and validation
- Added parsing of annotation `id` into `envelopeId`, `receiverId`, `index`, and `internalType`.
- Added validation for `id` format, ensuring it has exactly 4 parts and numeric checks for relevant fields.
- Throws `BurnAnnotationException` if `id` is null, empty, or incorrectly formatted.
- Maintains existing functionality for adding image, ink, and widget annotations.
2025-10-07 21:31:38 +02:00
a29f918125 fix(DependencyInjection): update to scan the assembly of EnvelopeReceiver instead of Config 2025-10-07 18:09:14 +02:00
3f116ce11a refactor(annotation): generate deterministic annotation IDs based on envelopeId, receiverId, and element index 2025-10-07 09:41:02 +02:00
41738bb36c refactor(annotation): add envelope id and receiver id input parameters 2025-10-06 17:12:06 +02:00
320b2ecc77 refactor(AnnotationData): add SignatureAnnotations-getter method to split signatures 2025-10-06 17:08:44 +02:00
b02cc3d7a4 refactor(PDFBurner): convert to Sub 2025-10-06 14:39:55 +02:00
14f2d9b6af refactor(PDFBurner): remove sigAnnotType parameter from AddInstantJSONAnnotationToPDF method 2025-10-06 13:54:56 +02:00
df74267616 refactor(PDFBurner): Vereinfachung der PDFBurner-Annotationsmethoden und Verbesserung der Fehlerbehandlung
- Methoden für Annotationen (AddInstantJSONAnnotationToPDF, AddImageAnnotation, AddInkAnnotation, AddFormFieldValue) auf Rückgabe-Typ Void umgestellt.
- Interne Try/Catch-Blöcke und das Unterdrücken von Ausnahmen in Hilfsmethoden entfernt.
- Fehlerbehandlung in BurnInstantJSONAnnotationsToPDF zentralisiert, mit Try/Catch für das Hinzufügen von Annotationen.
- Exit Select-Anweisungen für bessere Lesbarkeit in Select Case-Blöcken hinzugefügt.
- Import von DevExpress.DataProcessing ergänzt.
2025-10-06 10:29:29 +02:00
42870b973d refactor(frmFinalizePDF): configure Factory.Shared 2025-10-01 16:52:05 +02:00
33041a8b96 update to add triggers as dictionary 2025-10-01 15:39:08 +02:00
79db05be26 update to use Factory.Shared 2025-10-01 15:18:58 +02:00
f24a218d12 refactor(FinalizeDocumentJob): add EnvelopeGeneratorInfrastructure-Services 2025-10-01 14:44:47 +02:00
44a9971cf8 refactor(DependencyInjection.Config): add AddSQLExecutor method 2025-10-01 14:08:41 +02:00
82d4b7ec6a feat(infrastructure): refactor DIExtensions for DbContext registration
* Removed `dbContextOptions` parameter from `AddEnvelopeGeneratorInfrastructureServices`
* Moved `AddDbContext` registration into `Config` class with overloads for both `Action<DbContextOptionsBuilder>` and `Action<IServiceProvider, DbContextOptionsBuilder>`
* Simplified service registration flow and improved extensibility
2025-10-01 13:25:52 +02:00
9472322c1d fix(dbcontext): add conditional nullable annotation for ILogger parameter on .NET builds 2025-10-01 13:04:44 +02:00
53a656f6ee move DbTriggerParams to Infrastructure layer.
- createConfig for flexable configuration
2025-10-01 12:59:55 +02:00
ca24afe3c6 refactor(dbcontext): add NET/NETFRAMEWORK conditional compilation
- Wrapped `using` directives with `#if NET` and `#elif NETFRAMEWORK`
- Applied conditional inheritance for `IUserManagerDbContext` and `IMailDbContext`
- Made `EmailOut` DbSet and triggers only available in `NET` builds
- Adjusted `_logger` nullability for NET vs NETFRAMEWORK targets
- Ensured `modelBuilder.ConfigureUserManager()` only runs in NET builds
2025-10-01 11:17:27 +02:00
9c867ac8aa refactor(DIExtensions): Hinzufügen einer bedingten NET/NETFRAMEWORK-Unterstützung in DIExtensions
- Umschlossene Repository- und Executor-Registrierungen mit `#if NET`, um die Kompatibilität zwischen .NET und .NET Framework sicherzustellen
- Hinzufügen des Abschnitts `#elif NETFRAMEWORK` für frameworkspezifische Importe
- Verschieben der SQLExecutor- und Dapper-Typzuordnung unter bedingte Kompilierung
- Anpassen der Methodensignaturen zur Unterstützung bedingter nullbarer Parameter
2025-10-01 10:51:50 +02:00
12063f36de refactor(Infrastructure): update Executor, Migrations and Repositories to be compiled only in .NET 2025-10-01 10:36:57 +02:00
167ea1444b update core packages 2025-10-01 10:00:11 +02:00
794029f0e5 chore(Infrastructure): update csproj to support NET 4.6.2 2025-10-01 09:57:47 +02:00
04b3d630fe update to ignore appsettings.migration.json 2025-09-29 16:45:55 +02:00
d39a3d283d bump to 3.4.1 2025-09-29 16:18:51 +02:00
7cae9a5291 feat(pdf): add overload for Page to apply design across all pages
- Introduced Page(Action<PdfPage>) method to apply design logic to every page in the document
- Simplified Background method by replacing per-page iteration with new Page overload
- Improved readability and maintainability by removing duplicate page loop logic
2025-09-29 15:43:55 +02:00
6f31d7b1d0 refactor(pdf): optimize background rendering with single concat per page
- Added `System.Linq` import to enable distinct and ordered page index selection
- Applied `ConcatMatrix` transformation once per page instead of per signature
- Improved performance and reduced redundant operations in `Background` method
2025-09-29 15:06:24 +02:00
06431028cb refactor(EnvelopeLocked): add if smsExpiration-statetment to timer script 2025-09-29 14:04:24 +02:00
eafcd79749 create appsettings.Logging 2025-09-29 10:58:34 +02:00
78473a45f1 move TFARegParams to appsettings.Security 2025-09-29 10:55:31 +02:00
5c10636e37 refactor(appsettings.GSM): create and move GtxMessagingParams 2025-09-29 10:50:42 +02:00
91c8043a23 refactor: move TFARegParams to appsettings.UI 2025-09-29 10:48:36 +02:00
5e77b300d6 fix: add PSPDFKitLicenseKey 2025-09-29 10:46:01 +02:00
ec30c86da1 move DisableMultiLanguage parameter to UI 2025-09-29 10:37:27 +02:00
341cb175a9 refactor(appsettings): add appsettings.Security 2025-09-29 10:34:52 +02:00
cccbb36f94 refactor(appsettings.UI): add appsettings for UI 2025-09-29 10:26:21 +02:00
c75877b19e add appsettings.Database 2025-09-29 10:08:57 +02:00
dde855a08f refactor(appsettings.Mail): create to hold mail and message configurations 2025-09-29 09:54:17 +02:00
247ab38536 refactor(appsettings.Annotation): create to handle Annotation para,eters 2025-09-29 09:39:47 +02:00
737df03f01 refactor(Program): update to scan all appsettings.*.json's 2025-09-29 09:26:23 +02:00
7e1ef838d7 chore(Web): bump to 3.4 2025-09-26 16:38:35 +02:00
16657f6a31 refactor(Pdf): Add Background-method to place a background behind the signatures. 2025-09-26 16:00:25 +02:00
bf0bd8e9e7 refactor(ISignature): create to handle common properties of a signature
- implement to entity and dto
2025-09-25 16:14:59 +02:00
94ce416aa1 refactor(Pdf); rename OutputStream as ExportStream
- rename ToBytes extension method as ExportAsBytes
2025-09-25 12:52:50 +02:00
7964cc44fb refactor(Extensions): add ToBytes shortcut method 2025-09-25 12:47:03 +02:00
b0b734ecfb refactor(Edit): rename as Pdf
- add Page and Design methods as shortcut methods
2025-09-25 11:06:03 +02:00
2d6347ffa6 refactor(Edit): Dokument-Methode zum Bearbeiten von PDF-Dokumenten hinzufügen 2025-09-25 10:19:11 +02:00
ac29fac88d add OutputStream getter 2025-09-24 17:49:15 +02:00
54c21556f6 refactor(Edit): add Finalizer region 2025-09-24 16:08:59 +02:00
ed4fd6ce96 feat(Edit): created to handle pdf edit operations fluently 2025-09-24 16:07:51 +02:00
0fa641c15d feat(Extensions): Add PDF editing extension methods using iText
- Introduced `Edit` extension methods for `Stream` and `byte[]` to allow
  in-place PDF modifications via a `PdfDocument` action.
- Supports both .NET and .NET Framework projects.
- Ensures proper disposal of streams and PdfDocument instances.
2025-09-24 14:12:35 +02:00
8709bd5c2e feat(PdfEditor): Erstellen ein PDF-Bearbeitungsprojekt, das sowohl .NET als auch das .NET Framework unterstützt. 2025-09-24 13:08:56 +02:00
7a6f2a3304 refactor(EnvelopeController): remove unnecessary document assigment 2025-09-24 10:07:51 +02:00
b5d744c1cd fix(annotation): invoke sigature background creation to fix z-index problem 2025-09-23 19:25:09 +02:00
a1f4898c35 refactor(annotation.js): split to regions 2025-09-23 18:08:08 +02:00
841cc4fd8d refactor(annotations.js): update createAnnotations to return signatures and remove instance input 2025-09-22 17:19:00 +02:00
e2df610544 refactor(EnvelopeController): update EnvelopeReceiverReadOnly to use without then-calback-method 2025-09-22 13:26:09 +02:00
95fd16fff0 Download the relevant Google font locally 2025-09-22 12:52:12 +02:00
4fcef41fc0 minimize return statement 2025-09-19 15:28:11 +02:00
9a2959b307 remvoe createElementFromHTML 2025-09-19 15:26:20 +02:00
d51c7ac5ae convert to function 2025-09-19 15:23:40 +02:00
925187e294 remove UI class to simplify 2025-09-19 15:22:48 +02:00
80c6b5bc64 update signatureCount to init in constructor 2025-09-19 15:18:50 +02:00
7d4106d0a5 refactor(app): simplify App initialization and rename PSPDFKit instance
- Initialize `currentDocument` and `currentReceiver` directly in constructor
- Replace `Instance` with `pdfKit` for clearer naming
- Remove redundant envelope/document loading in `init`
- Update all method references to use `this.pdfKit`
2025-09-19 15:16:59 +02:00
3b9b930b82 remove ActionType object 2025-09-19 15:07:24 +02:00
9ec6fcf272 update to use roload instead of rejection redirection 2025-09-19 15:03:23 +02:00
c38a50af34 make env.xsrfToken lazy loading
- remove env.envKey
2025-09-19 14:58:14 +02:00
877c88d52b refactor: replace repeated GET+JSON parsing with reusable getJson helper 2025-09-19 13:58:07 +02:00
9c730e8f42 refactor(api-service): rename as envelope-api 2025-09-19 13:53:12 +02:00
7a1c669fb0 move getAnnotationParams to api-service
- remove network.js
2025-09-19 13:50:19 +02:00
62411b4d2b move logout-method to api-service 2025-09-19 13:36:47 +02:00
f04fcde7b9 move setLanguage to api-service 2025-09-19 13:32:01 +02:00
2a352265a8 freeze env and url objects 2025-09-19 13:18:45 +02:00
ceff62cb64 refactor: unify and simplify request helper methods
This commit:
- Replaces `createRequest`, `createPost`, and `submitForm` with a single `sendRequest` helper.
- Adds `getRequest` and `postRequest` wrappers for clarity.
- Removes redundant content type constants and parameters.
- Updates envelope-related methods (`signEnvelope`, `rejectEnvelope`, `shareEnvelope`) to use the new request helpers.
- Simplifies `redirect` and `redirRejected` functions.
2025-09-19 13:16:48 +02:00
f1f4c6eaef create envelope region 2025-09-19 11:52:37 +02:00
f8297808ec create request helper methods region 2025-09-19 11:50:25 +02:00
0fc6fd650c refactor(postAnnotation): rename as signEnvelope 2025-09-19 11:49:14 +02:00
13af2ae3e1 refactor: move postAnnotations to ap-service 2025-09-19 11:47:49 +02:00
3914b827fb refactor(url): convert getter methods to variables 2025-09-19 11:44:23 +02:00
a5ab217ac6 refactor(env): remove lazy loading to simplfy 2025-09-19 11:42:37 +02:00
4075739522 Split the URL into two objects as URL and environment 2025-09-19 11:41:41 +02:00
8abf8260bf update to use lazy loading 2025-09-19 11:35:07 +02:00
451e7e7daa feat(lazy): created to handle lazy loading 2025-09-19 10:36:14 +02:00
6622442d95 convert to camel case 2025-09-19 10:20:23 +02:00
dcd5dc71de covnert Url to object 2025-09-19 10:07:38 +02:00
3fe09f8382 rename API as Url 2025-09-19 10:06:09 +02:00
bac9aebbc3 refactor(api): replace arrow functions with function declarations and simplify defaults
- Removed unused Content class
- Converted async arrow functions to standard function declarations
- Added default 'application/json' for createRequest and createPost
- Improved readability and consistency across API helpers
2025-09-19 09:59:57 +02:00
a8a73724e6 refactor(EnvelopeController): add logic to check the claims with role 2025-09-18 20:48:09 +02:00
8059e0aae4 remove old routes 2025-09-18 19:53:09 +02:00
4c5116695b remove envelope receiver id input 2025-09-18 19:51:43 +02:00
ffa31fbebc change LogInEnvelope route 2025-09-18 18:37:10 +02:00
e536e523b8 fix(EnvelopeController): rename CreateEnvelopeLockedView as EnvelopeLocked 2025-09-18 18:35:37 +02:00
1d64c19605 add cancelation token 2025-09-18 18:19:22 +02:00
29e6ba8733 Refactoring (EnvelopeController): Vereinheitlichung der Verarbeitung von gesperrten Ansichten
- Methode „CreateEnvelopeLockedView” hinzugefügt, um die Logik für die Anzeige gesperrter/umschlossener Ansichten zu zentralisieren
- Aktion „Main“ aktualisiert, um „CreateEnvelopeLockedView“ anstelle von Redirect zu verwenden
- Veraltete Methode „EnvelopeLocked“ entfernt
- TFA-bezogene Ansichten und Handler aktualisiert, um auf „CreateEnvelopeLockedView“ anstelle von „EnvelopeLocked“ zu verweisen
- Dokumentenlade- und Anmeldelogik in wiederverwendbare Methoden vereinfacht
2025-09-18 18:18:59 +02:00
2e6eeafd74 refactor(EnvelopeController): add read-only region 2025-09-18 17:22:40 +02:00
643501f484 refactor(EnvelopeController): simplify EnvelopeController actions and view handling
- Added overload of CreateShowEnvelopeView(EnvelopeReceiverDto) to remove redundant id parsing logic
- Refactored EnvelopeLocked action to receive EnvelopeReceiverDto directly instead of fetching inside
- Centralized ViewData assignments for cleaner envelope rendering
- Improved error logging to include envelope UUID and receiver signature where applicable
- Adjusted EnvelopeLocked GET to return explicit "EnvelopeLocked" view for unauthenticated users
2025-09-18 17:14:28 +02:00
0c900d219c refactor(EnvelopeController): add Send Access Code-region 2025-09-18 16:19:40 +02:00
8d8757810c refactor(EnvelopeController): move rejection and signing check to Main-endpoint 2025-09-18 16:15:33 +02:00
9dec681ce5 Home und View in Home und Envelope unterteilen 2025-09-18 14:01:21 +02:00
01ec2b3df2 refactor(HomeController): Als Home- und Envelope-Controller aufteilen 2025-09-18 13:16:33 +02:00
d64d46920a refactor(api-services): change wrong url route 2025-09-18 12:59:01 +02:00
6147a619a8 refactor(EnvelopeReceiverReadOnly): fix nullability problem 2025-09-18 12:33:00 +02:00
6327fef2e0 chore(Web): bump to 3.3.0 2025-09-17 17:48:58 +02:00
d0bfe795d7 refactor(HomeController): Ändern Sie den Routenparameter „EnvelopeReceiverReadOnly” von einem String-Schlüssel zu einer langen ID
- Aktualisieren Sie „MainAsync”, um mit einer geparsten schreibgeschützten ID anstelle eines String-Schlüssels zu „EnvelopeReceiverReadOnly” umzuleiten
- Ändern Sie die Aktionssignatur „EnvelopeReceiverReadOnly”, um „long readOnlyId” anstelle von „[FromRoute] string readOnlyKey” zu akzeptieren
- Inline-Schlüssel-Decodierungs-/Validierungslogik entfernt und Decodierung an `MainAsync` delegiert
- Protokollmeldungen angepasst, um `ReadOnly-Id` anstelle von `ReadOnly-key` widerzuspiegeln
2025-09-17 13:59:31 +02:00
10b1de4cf0 remove envelopeRejected-endpoint 2025-09-17 13:17:25 +02:00
cf3535b4de refactor(HomeController): remove envelopeSigned endpoint 2025-09-17 13:07:06 +02:00
56074c2b9f refactor(HomeController): add fromRoute attributes 2025-09-17 10:49:18 +02:00
c41c521fca rename postEnvelope as postAnnotation 2025-09-17 10:40:17 +02:00
7bc6cc92a0 remove setLangAsync-method 2025-09-17 10:37:43 +02:00
660a4c24df refactor(EnvelopeController): Umbenennen in AnnotationController 2025-09-17 10:35:11 +02:00
5d65f58a55 feat(EnvelopeController): sign out user after envelope actions
- Added `HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme)`
  to `CreateOrUpdate` and `Reject` endpoints in `EnvelopeController`
- Ensures user session is cleared after completing or rejecting envelope actions
- Updated using directives to include `Microsoft.AspNetCore.Authentication`
  and `Microsoft.AspNetCore.Authentication.Cookies`
2025-09-17 10:31:09 +02:00
6691471276 fix(pdfburner): correct y-position adjustment for signature seal annotations
Previously, image annotations for signature seals used a static yOffset
when combined with ink annotations, which caused positioning issues.
This change calculates the y-position of the signature annotation
relative to the next annotation and applies it only for the first seal.

- Added `yPosOfSigAnnot` calculation for precise vertical placement.
- Updated `AddInstantJSONAnnotationToPDF` to overwrite bbox.y for seals.
- Removed hardcoded ink offset logic.
2025-09-16 17:37:20 +02:00
b2bfc11713 change the y-offset of ANNOTATION_TYPE_IMAGE 2025-09-16 16:54:44 +02:00
5d758601b9 Merge branch 'master' of http://git.dd:3000/AppStd/EnvelopeGenerator 2025-09-16 11:28:32 +02:00
Developer01
210bb821da DocResult-Column was defined wrong. Correct: DOC_RESULT 2025-09-16 09:02:38 +02:00
Developer01
3ac61e75f5 ReceiverVM Vereinheitlichung 2025-09-16 08:05:50 +02:00
eb353ab772 chore(Web): bump to 3.2.3 2025-09-15 15:51:10 +02:00
991943d6bd refactor(SendMailHandler): remove TextToHtml 2025-09-15 14:23:48 +02:00
b5fec7bb46 refactor(DocSignedNotificationTests): add again EmailOut DbRepository using Fake.EGDbContext2Prod
- create base EGDbContextBase to be able to add custom DbContextOptions
2025-09-15 14:02:58 +02:00
9eaa777fb6 feat(Fake): enhance Fake host with production DbContext support
- Added `EGDbContext2Prod` class to allow connecting to production database in tests
 - Updated `CreateHost` to register `EGDbContext2Prod` with SQL Server connection string
 - Added `EnvelopeGenerator.Application.Common.Configurations` and logging support
 - Refactored service registration ordering for clarity
2025-09-15 13:18:30 +02:00
ccc4e948f3 feat(TestBase): seed real email templates in TestBase setup
- Added `RealEmailTemplates` property with predefined email templates.
- Populated the repository with these templates in the `Setup` method.
- Ensures tests have consistent, realistic email data available.
2025-09-15 12:44:36 +02:00
d5afb2201c refactor(DocSignedNotificationTests): DocSignedNotificationTests aktualisieren, um SendSignedMailHandler zu verwenden
- SendSignedMailHandler in Testdiensten registrieren
- Test1 umbenennen → SendSignedMailHandler_ShouldNotThrow
- Sicherstellen, dass die Handler-Ausführung keinen Fehler auslöst
2025-09-15 11:18:44 +02:00
7fbf0ebbfc refactor(TestBase): add ConfigureServices-callback method to be able to add custom services to testes 2025-09-15 11:00:00 +02:00
cb0c361cdb test: enhance DocSignedNotificationTests with AutoMapper and notification mapping 2025-09-15 10:48:25 +02:00
796c59cd38 chore: update Core.Abstraction.Application to 1.3.1
- update DigitalData.Core.Abstractions to 4.1.1
 - update DigitalData.Core.Infrastructure to 2.4.1
2025-09-15 10:38:01 +02:00
86780477fe refactor(Fake): update CreateReceiverCommand to be able to add email address 2025-09-12 14:19:57 +02:00
27a2d5ecc4 refactor(DIExtensions): update to scan EmailProfilerDispatcher 2025-09-12 13:50:48 +02:00
83460bd92b refactor(DIExtensions): update dependecy inejction to scan assemblies 2025-09-12 13:40:53 +02:00
b8bffdb4bc chore: update package versions and to solve vulnerabilities 2025-09-12 13:21:28 +02:00
df66060de3 bump to 3.2.2 2025-09-11 09:29:34 +02:00
4da7445271 remove removed reference 2025-09-11 09:25:22 +02:00
0a9e1dccb9 refactor(Interfaces): move Interfaces to Common 2025-09-10 16:42:52 +02:00
95b54fa1f1 feat(JsonExtensions): create to be able to make fluent Json serilization 2025-09-10 15:55:56 +02:00
e990a466aa refactor(AnnotationHandler): update to use System.Text.Json.JsonSerializer 2025-09-10 15:38:05 +02:00
4eb6d87770 add MsgBox 2025-09-10 15:02:19 +02:00
e2c3d4ad52 init DocSignedNotificationTest 2025-09-10 14:21:14 +02:00
a9dda12bf9 chore(Web): bump to 3.2.1 2025-09-10 14:08:27 +02:00
fd157c4443 refactor(ReadEnvelopeReceiverQuery): add receiver filter to signatures 2025-09-10 14:04:48 +02:00
f940caad1c chore(Web): bump to 3.2.0 2025-09-10 13:42:08 +02:00
272 changed files with 12406 additions and 6376 deletions

View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>EnvelopeGenerator.Application.VB</RootNamespace>
<TargetFrameworks>net7.0;net8.0;net9.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DevExpress.Data" Version="21.2.4" />
<PackageReference Include="DevExpress.Reporting.Core" Version="21.2.4" />
<PackageReference Include="DevExpress.Win" Version="21.2.0" />
<PackageReference Include="DevExpress.Xpo" Version="21.2.4" />
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
<Compile Update="Reports\rptEnvelopeHistory.vb">
<SubType>Component</SubType>
</Compile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,730 @@
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Public Class rptEnvelopeHistory
Inherits DevExpress.XtraReports.UI.XtraReport
'XtraReport overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Designer
'It can be modified using the Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container()
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(rptEnvelopeHistory))
Me.TopMargin = New DevExpress.XtraReports.UI.TopMarginBand()
Me.BottomMargin = New DevExpress.XtraReports.UI.BottomMarginBand()
Me.XrLabel1 = New DevExpress.XtraReports.UI.XRLabel()
Me.pageInfo1 = New DevExpress.XtraReports.UI.XRPageInfo()
Me.pageInfo2 = New DevExpress.XtraReports.UI.XRPageInfo()
Me.ReportHeader = New DevExpress.XtraReports.UI.ReportHeaderBand()
Me.label1 = New DevExpress.XtraReports.UI.XRLabel()
Me.XrTable3 = New DevExpress.XtraReports.UI.XRTable()
Me.XrTableRow8 = New DevExpress.XtraReports.UI.XRTableRow()
Me.XrTableCell13 = New DevExpress.XtraReports.UI.XRTableCell()
Me.XrTableCell15 = New DevExpress.XtraReports.UI.XRTableCell()
Me.XrTableRow9 = New DevExpress.XtraReports.UI.XRTableRow()
Me.XrTableCell14 = New DevExpress.XtraReports.UI.XRTableCell()
Me.XrTableCell17 = New DevExpress.XtraReports.UI.XRTableCell()
Me.XrTableCell16 = New DevExpress.XtraReports.UI.XRTableCell()
Me.XrTableCell18 = New DevExpress.XtraReports.UI.XRTableCell()
Me.XrTableRow10 = New DevExpress.XtraReports.UI.XRTableRow()
Me.XrTableCell19 = New DevExpress.XtraReports.UI.XRTableCell()
Me.XrTableCell20 = New DevExpress.XtraReports.UI.XRTableCell()
Me.XrTableCell21 = New DevExpress.XtraReports.UI.XRTableCell()
Me.XrTableCell22 = New DevExpress.XtraReports.UI.XRTableCell()
Me.XrTableRow11 = New DevExpress.XtraReports.UI.XRTableRow()
Me.XrTableCell23 = New DevExpress.XtraReports.UI.XRTableCell()
Me.XrTableCell24 = New DevExpress.XtraReports.UI.XRTableCell()
Me.XrTableCell25 = New DevExpress.XtraReports.UI.XRTableCell()
Me.XrTableCell26 = New DevExpress.XtraReports.UI.XRTableCell()
Me.GroupHeader1 = New DevExpress.XtraReports.UI.GroupHeaderBand()
Me.table1 = New DevExpress.XtraReports.UI.XRTable()
Me.tableRow1 = New DevExpress.XtraReports.UI.XRTableRow()
Me.tableCell1 = New DevExpress.XtraReports.UI.XRTableCell()
Me.tableCell2 = New DevExpress.XtraReports.UI.XRTableCell()
Me.tableCell3 = New DevExpress.XtraReports.UI.XRTableCell()
Me.Detail = New DevExpress.XtraReports.UI.DetailBand()
Me.table2 = New DevExpress.XtraReports.UI.XRTable()
Me.tableRow2 = New DevExpress.XtraReports.UI.XRTableRow()
Me.tableCell4 = New DevExpress.XtraReports.UI.XRTableCell()
Me.tableCell5 = New DevExpress.XtraReports.UI.XRTableCell()
Me.tableCell6 = New DevExpress.XtraReports.UI.XRTableCell()
Me.Title = New DevExpress.XtraReports.UI.XRControlStyle()
Me.DetailCaption1 = New DevExpress.XtraReports.UI.XRControlStyle()
Me.DetailData1 = New DevExpress.XtraReports.UI.XRControlStyle()
Me.DetailData3_Odd = New DevExpress.XtraReports.UI.XRControlStyle()
Me.PageInfo = New DevExpress.XtraReports.UI.XRControlStyle()
Me.GalleryDropDown1 = New DevExpress.XtraBars.Ribbon.GalleryDropDown(Me.components)
Me.ObjectDataSource1 = New DevExpress.DataAccess.ObjectBinding.ObjectDataSource(Me.components)
CType(Me.XrTable3, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.table1, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.table2, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.GalleryDropDown1, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.ObjectDataSource1, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me, System.ComponentModel.ISupportInitialize).BeginInit()
'
'TopMargin
'
Me.TopMargin.Dpi = 254.0!
Me.TopMargin.HeightF = 190.6042!
Me.TopMargin.Name = "TopMargin"
'
'BottomMargin
'
Me.BottomMargin.Controls.AddRange(New DevExpress.XtraReports.UI.XRControl() {Me.XrLabel1, Me.pageInfo1, Me.pageInfo2})
Me.BottomMargin.Dpi = 254.0!
Me.BottomMargin.Name = "BottomMargin"
'
'XrLabel1
'
Me.XrLabel1.BorderColor = System.Drawing.Color.FromArgb(CType(CType(165, Byte), Integer), CType(CType(36, Byte), Integer), CType(CType(49, Byte), Integer))
Me.XrLabel1.Borders = DevExpress.XtraPrinting.BorderSide.Top
Me.XrLabel1.Dpi = 254.0!
Me.XrLabel1.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Bold)
Me.XrLabel1.LocationFloat = New DevExpress.Utils.PointFloat(896.5417!, 0!)
Me.XrLabel1.Name = "XrLabel1"
Me.XrLabel1.Padding = New DevExpress.XtraPrinting.PaddingInfo(0, 0, 0, 0, 254.0!)
Me.XrLabel1.SizeF = New System.Drawing.SizeF(645.5836!, 58.0!)
Me.XrLabel1.StyleName = "Title"
Me.XrLabel1.StylePriority.UseBorderColor = False
Me.XrLabel1.StylePriority.UseBorders = False
Me.XrLabel1.StylePriority.UseFont = False
Me.XrLabel1.StylePriority.UsePadding = False
Me.XrLabel1.Text = "Erstellt mit SignFlow"
'
'pageInfo1
'
Me.pageInfo1.BorderColor = System.Drawing.Color.FromArgb(CType(CType(165, Byte), Integer), CType(CType(36, Byte), Integer), CType(CType(49, Byte), Integer))
Me.pageInfo1.Borders = DevExpress.XtraPrinting.BorderSide.Top
Me.pageInfo1.Dpi = 254.0!
Me.pageInfo1.LocationFloat = New DevExpress.Utils.PointFloat(0!, 0!)
Me.pageInfo1.Name = "pageInfo1"
Me.pageInfo1.PageInfo = DevExpress.XtraPrinting.PageInfo.DateTime
Me.pageInfo1.SizeF = New System.Drawing.SizeF(896.5417!, 58.0!)
Me.pageInfo1.StyleName = "PageInfo"
Me.pageInfo1.StylePriority.UseBorderColor = False
Me.pageInfo1.StylePriority.UseBorders = False
Me.pageInfo1.TextFormatString = "{0:dddd, d. MMMM yyyy HH:mm}"
'
'pageInfo2
'
Me.pageInfo2.BorderColor = System.Drawing.Color.FromArgb(CType(CType(165, Byte), Integer), CType(CType(36, Byte), Integer), CType(CType(49, Byte), Integer))
Me.pageInfo2.Borders = DevExpress.XtraPrinting.BorderSide.Top
Me.pageInfo2.Dpi = 254.0!
Me.pageInfo2.LocationFloat = New DevExpress.Utils.PointFloat(1542.125!, 0!)
Me.pageInfo2.Name = "pageInfo2"
Me.pageInfo2.SizeF = New System.Drawing.SizeF(357.875!, 58.0!)
Me.pageInfo2.StyleName = "PageInfo"
Me.pageInfo2.StylePriority.UseBorderColor = False
Me.pageInfo2.StylePriority.UseBorders = False
Me.pageInfo2.TextAlignment = DevExpress.XtraPrinting.TextAlignment.TopRight
Me.pageInfo2.TextFormatString = "Seite {0} von {1}"
'
'ReportHeader
'
Me.ReportHeader.Controls.AddRange(New DevExpress.XtraReports.UI.XRControl() {Me.label1, Me.XrTable3})
Me.ReportHeader.Dpi = 254.0!
Me.ReportHeader.HeightF = 406.0843!
Me.ReportHeader.Name = "ReportHeader"
'
'label1
'
Me.label1.BackColor = System.Drawing.Color.FromArgb(CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer))
Me.label1.BorderColor = System.Drawing.Color.FromArgb(CType(CType(165, Byte), Integer), CType(CType(36, Byte), Integer), CType(CType(49, Byte), Integer))
Me.label1.Borders = DevExpress.XtraPrinting.BorderSide.Bottom
Me.label1.BorderWidth = 2.0!
Me.label1.Dpi = 254.0!
Me.label1.Font = New System.Drawing.Font("Segoe UI", 14.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.label1.ForeColor = System.Drawing.Color.Black
Me.label1.LocationFloat = New DevExpress.Utils.PointFloat(0.0002422333!, 0!)
Me.label1.Name = "label1"
Me.label1.Padding = New DevExpress.XtraPrinting.PaddingInfo(10, 10, 5, 5, 254.0!)
Me.label1.SizeF = New System.Drawing.SizeF(1900.0!, 77.32857!)
Me.label1.StyleName = "Title"
Me.label1.StylePriority.UseBackColor = False
Me.label1.StylePriority.UseBorderColor = False
Me.label1.StylePriority.UseBorders = False
Me.label1.StylePriority.UseBorderWidth = False
Me.label1.StylePriority.UseFont = False
Me.label1.StylePriority.UseForeColor = False
Me.label1.StylePriority.UsePadding = False
Me.label1.Text = "Signierungszertifikat"
'
'XrTable3
'
Me.XrTable3.Dpi = 254.0!
Me.XrTable3.LocationFloat = New DevExpress.Utils.PointFloat(0.0002422333!, 96.60422!)
Me.XrTable3.Name = "XrTable3"
Me.XrTable3.OddStyleName = "DetailData3_Odd"
Me.XrTable3.Rows.AddRange(New DevExpress.XtraReports.UI.XRTableRow() {Me.XrTableRow8, Me.XrTableRow9, Me.XrTableRow10, Me.XrTableRow11})
Me.XrTable3.SizeF = New System.Drawing.SizeF(1900.0!, 284.4801!)
'
'XrTableRow8
'
Me.XrTableRow8.Cells.AddRange(New DevExpress.XtraReports.UI.XRTableCell() {Me.XrTableCell13, Me.XrTableCell15})
Me.XrTableRow8.Dpi = 254.0!
Me.XrTableRow8.Name = "XrTableRow8"
Me.XrTableRow8.Weight = 1.0R
'
'XrTableCell13
'
Me.XrTableCell13.BackColor = System.Drawing.Color.FromArgb(CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer))
Me.XrTableCell13.BorderColor = System.Drawing.Color.FromArgb(CType(CType(165, Byte), Integer), CType(CType(36, Byte), Integer), CType(CType(49, Byte), Integer))
Me.XrTableCell13.Borders = DevExpress.XtraPrinting.BorderSide.Bottom
Me.XrTableCell13.BorderWidth = 1.0!
Me.XrTableCell13.Dpi = 254.0!
Me.XrTableCell13.ForeColor = System.Drawing.Color.Black
Me.XrTableCell13.Name = "XrTableCell13"
Me.XrTableCell13.StyleName = "DetailCaption1"
Me.XrTableCell13.StylePriority.UseBackColor = False
Me.XrTableCell13.StylePriority.UseBorderColor = False
Me.XrTableCell13.StylePriority.UseBorders = False
Me.XrTableCell13.StylePriority.UseBorderWidth = False
Me.XrTableCell13.StylePriority.UseForeColor = False
Me.XrTableCell13.Text = "Ersteller"
Me.XrTableCell13.Weight = 0.38139956730411484R
'
'XrTableCell15
'
Me.XrTableCell15.BackColor = System.Drawing.Color.FromArgb(CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer))
Me.XrTableCell15.BorderColor = System.Drawing.Color.FromArgb(CType(CType(165, Byte), Integer), CType(CType(36, Byte), Integer), CType(CType(49, Byte), Integer))
Me.XrTableCell15.Borders = DevExpress.XtraPrinting.BorderSide.Bottom
Me.XrTableCell15.BorderWidth = 1.0!
Me.XrTableCell15.Dpi = 254.0!
Me.XrTableCell15.ForeColor = System.Drawing.Color.Black
Me.XrTableCell15.Name = "XrTableCell15"
Me.XrTableCell15.StyleName = "DetailCaption1"
Me.XrTableCell15.StylePriority.UseBackColor = False
Me.XrTableCell15.StylePriority.UseBorderColor = False
Me.XrTableCell15.StylePriority.UseBorders = False
Me.XrTableCell15.StylePriority.UseBorderWidth = False
Me.XrTableCell15.StylePriority.UseForeColor = False
Me.XrTableCell15.Text = "Umschlag"
Me.XrTableCell15.Weight = 0.49859081604996847R
'
'XrTableRow9
'
Me.XrTableRow9.Cells.AddRange(New DevExpress.XtraReports.UI.XRTableCell() {Me.XrTableCell14, Me.XrTableCell17, Me.XrTableCell16, Me.XrTableCell18})
Me.XrTableRow9.Dpi = 254.0!
Me.XrTableRow9.Name = "XrTableRow9"
Me.XrTableRow9.Weight = 1.0R
'
'XrTableCell14
'
Me.XrTableCell14.BackColor = System.Drawing.Color.White
Me.XrTableCell14.BorderColor = System.Drawing.Color.Empty
Me.XrTableCell14.Borders = DevExpress.XtraPrinting.BorderSide.None
Me.XrTableCell14.Dpi = 254.0!
Me.XrTableCell14.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.XrTableCell14.ForeColor = System.Drawing.Color.Black
Me.XrTableCell14.Multiline = True
Me.XrTableCell14.Name = "XrTableCell14"
Me.XrTableCell14.StyleName = "DetailCaption1"
Me.XrTableCell14.StylePriority.UseBackColor = False
Me.XrTableCell14.StylePriority.UseBorderColor = False
Me.XrTableCell14.StylePriority.UseBorders = False
Me.XrTableCell14.StylePriority.UseFont = False
Me.XrTableCell14.StylePriority.UseForeColor = False
Me.XrTableCell14.Text = "Name"
Me.XrTableCell14.Weight = 0.11578820509129036R
'
'XrTableCell17
'
Me.XrTableCell17.BackColor = System.Drawing.Color.White
Me.XrTableCell17.BorderColor = System.Drawing.Color.Empty
Me.XrTableCell17.Borders = DevExpress.XtraPrinting.BorderSide.None
Me.XrTableCell17.Dpi = 254.0!
Me.XrTableCell17.ExpressionBindings.AddRange(New DevExpress.XtraReports.UI.ExpressionBinding() {New DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[Envelope].[User].[FullName]")})
Me.XrTableCell17.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.XrTableCell17.ForeColor = System.Drawing.Color.Black
Me.XrTableCell17.Multiline = True
Me.XrTableCell17.Name = "XrTableCell17"
Me.XrTableCell17.StyleName = "DetailCaption1"
Me.XrTableCell17.StylePriority.UseBackColor = False
Me.XrTableCell17.StylePriority.UseBorderColor = False
Me.XrTableCell17.StylePriority.UseBorders = False
Me.XrTableCell17.StylePriority.UseFont = False
Me.XrTableCell17.StylePriority.UseForeColor = False
Me.XrTableCell17.Text = "XrTableCell17"
Me.XrTableCell17.Weight = 0.2656113622128245R
'
'XrTableCell16
'
Me.XrTableCell16.BackColor = System.Drawing.Color.White
Me.XrTableCell16.BorderColor = System.Drawing.Color.Empty
Me.XrTableCell16.Borders = DevExpress.XtraPrinting.BorderSide.None
Me.XrTableCell16.Dpi = 254.0!
Me.XrTableCell16.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.XrTableCell16.ForeColor = System.Drawing.Color.Black
Me.XrTableCell16.Multiline = True
Me.XrTableCell16.Name = "XrTableCell16"
Me.XrTableCell16.StyleName = "DetailCaption1"
Me.XrTableCell16.StylePriority.UseBackColor = False
Me.XrTableCell16.StylePriority.UseBorderColor = False
Me.XrTableCell16.StylePriority.UseBorders = False
Me.XrTableCell16.StylePriority.UseFont = False
Me.XrTableCell16.StylePriority.UseForeColor = False
Me.XrTableCell16.Text = "Titel"
Me.XrTableCell16.Weight = 0.11578821158083684R
'
'XrTableCell18
'
Me.XrTableCell18.BackColor = System.Drawing.Color.White
Me.XrTableCell18.BorderColor = System.Drawing.Color.Empty
Me.XrTableCell18.Borders = DevExpress.XtraPrinting.BorderSide.None
Me.XrTableCell18.Dpi = 254.0!
Me.XrTableCell18.ExpressionBindings.AddRange(New DevExpress.XtraReports.UI.ExpressionBinding() {New DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[Envelope].[Title]")})
Me.XrTableCell18.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.XrTableCell18.ForeColor = System.Drawing.Color.Black
Me.XrTableCell18.Multiline = True
Me.XrTableCell18.Name = "XrTableCell18"
Me.XrTableCell18.StyleName = "DetailCaption1"
Me.XrTableCell18.StylePriority.UseBackColor = False
Me.XrTableCell18.StylePriority.UseBorderColor = False
Me.XrTableCell18.StylePriority.UseBorders = False
Me.XrTableCell18.StylePriority.UseFont = False
Me.XrTableCell18.StylePriority.UseForeColor = False
Me.XrTableCell18.Text = "XrTableCell18"
Me.XrTableCell18.Weight = 0.38280260446913167R
'
'XrTableRow10
'
Me.XrTableRow10.Cells.AddRange(New DevExpress.XtraReports.UI.XRTableCell() {Me.XrTableCell19, Me.XrTableCell20, Me.XrTableCell21, Me.XrTableCell22})
Me.XrTableRow10.Dpi = 254.0!
Me.XrTableRow10.Name = "XrTableRow10"
Me.XrTableRow10.Weight = 1.0R
'
'XrTableCell19
'
Me.XrTableCell19.BackColor = System.Drawing.Color.White
Me.XrTableCell19.BorderColor = System.Drawing.Color.Empty
Me.XrTableCell19.Borders = DevExpress.XtraPrinting.BorderSide.None
Me.XrTableCell19.Dpi = 254.0!
Me.XrTableCell19.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.XrTableCell19.ForeColor = System.Drawing.Color.Black
Me.XrTableCell19.Multiline = True
Me.XrTableCell19.Name = "XrTableCell19"
Me.XrTableCell19.StyleName = "DetailCaption1"
Me.XrTableCell19.StylePriority.UseBackColor = False
Me.XrTableCell19.StylePriority.UseBorderColor = False
Me.XrTableCell19.StylePriority.UseBorders = False
Me.XrTableCell19.StylePriority.UseFont = False
Me.XrTableCell19.StylePriority.UseForeColor = False
Me.XrTableCell19.Text = "EmailAddress"
Me.XrTableCell19.Weight = 0.11578820509129036R
'
'XrTableCell20
'
Me.XrTableCell20.BackColor = System.Drawing.Color.White
Me.XrTableCell20.BorderColor = System.Drawing.Color.Empty
Me.XrTableCell20.Borders = DevExpress.XtraPrinting.BorderSide.None
Me.XrTableCell20.Dpi = 254.0!
Me.XrTableCell20.ExpressionBindings.AddRange(New DevExpress.XtraReports.UI.ExpressionBinding() {New DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[Envelope].[User].[EmailAddress]")})
Me.XrTableCell20.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.XrTableCell20.ForeColor = System.Drawing.Color.Black
Me.XrTableCell20.Multiline = True
Me.XrTableCell20.Name = "XrTableCell20"
Me.XrTableCell20.StyleName = "DetailCaption1"
Me.XrTableCell20.StylePriority.UseBackColor = False
Me.XrTableCell20.StylePriority.UseBorderColor = False
Me.XrTableCell20.StylePriority.UseBorders = False
Me.XrTableCell20.StylePriority.UseFont = False
Me.XrTableCell20.StylePriority.UseForeColor = False
Me.XrTableCell20.Text = "XrTableCell20"
Me.XrTableCell20.Weight = 0.2656113622128245R
'
'XrTableCell21
'
Me.XrTableCell21.BackColor = System.Drawing.Color.White
Me.XrTableCell21.BorderColor = System.Drawing.Color.Empty
Me.XrTableCell21.Borders = DevExpress.XtraPrinting.BorderSide.None
Me.XrTableCell21.Dpi = 254.0!
Me.XrTableCell21.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.XrTableCell21.ForeColor = System.Drawing.Color.Black
Me.XrTableCell21.Multiline = True
Me.XrTableCell21.Name = "XrTableCell21"
Me.XrTableCell21.StyleName = "DetailCaption1"
Me.XrTableCell21.StylePriority.UseBackColor = False
Me.XrTableCell21.StylePriority.UseBorderColor = False
Me.XrTableCell21.StylePriority.UseBorders = False
Me.XrTableCell21.StylePriority.UseFont = False
Me.XrTableCell21.StylePriority.UseForeColor = False
Me.XrTableCell21.Text = "Umschlag-ID"
Me.XrTableCell21.Weight = 0.11578821158083684R
'
'XrTableCell22
'
Me.XrTableCell22.BackColor = System.Drawing.Color.White
Me.XrTableCell22.BorderColor = System.Drawing.Color.Empty
Me.XrTableCell22.Borders = DevExpress.XtraPrinting.BorderSide.None
Me.XrTableCell22.Dpi = 254.0!
Me.XrTableCell22.ExpressionBindings.AddRange(New DevExpress.XtraReports.UI.ExpressionBinding() {New DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[Envelope].[Uuid]")})
Me.XrTableCell22.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.XrTableCell22.ForeColor = System.Drawing.Color.Black
Me.XrTableCell22.Multiline = True
Me.XrTableCell22.Name = "XrTableCell22"
Me.XrTableCell22.StyleName = "DetailCaption1"
Me.XrTableCell22.StylePriority.UseBackColor = False
Me.XrTableCell22.StylePriority.UseBorderColor = False
Me.XrTableCell22.StylePriority.UseBorders = False
Me.XrTableCell22.StylePriority.UseFont = False
Me.XrTableCell22.StylePriority.UseForeColor = False
Me.XrTableCell22.Text = "XrTableCell22"
Me.XrTableCell22.Weight = 0.38280260446913167R
'
'XrTableRow11
'
Me.XrTableRow11.Cells.AddRange(New DevExpress.XtraReports.UI.XRTableCell() {Me.XrTableCell23, Me.XrTableCell24, Me.XrTableCell25, Me.XrTableCell26})
Me.XrTableRow11.Dpi = 254.0!
Me.XrTableRow11.Name = "XrTableRow11"
Me.XrTableRow11.Weight = 1.0R
'
'XrTableCell23
'
Me.XrTableCell23.BackColor = System.Drawing.Color.White
Me.XrTableCell23.BorderColor = System.Drawing.Color.Empty
Me.XrTableCell23.Borders = DevExpress.XtraPrinting.BorderSide.None
Me.XrTableCell23.Dpi = 254.0!
Me.XrTableCell23.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.XrTableCell23.ForeColor = System.Drawing.Color.Black
Me.XrTableCell23.Multiline = True
Me.XrTableCell23.Name = "XrTableCell23"
Me.XrTableCell23.StyleName = "DetailCaption1"
Me.XrTableCell23.StylePriority.UseBackColor = False
Me.XrTableCell23.StylePriority.UseBorderColor = False
Me.XrTableCell23.StylePriority.UseBorders = False
Me.XrTableCell23.StylePriority.UseFont = False
Me.XrTableCell23.StylePriority.UseForeColor = False
Me.XrTableCell23.Weight = 0.11578820509129036R
'
'XrTableCell24
'
Me.XrTableCell24.BackColor = System.Drawing.Color.White
Me.XrTableCell24.BorderColor = System.Drawing.Color.Empty
Me.XrTableCell24.Borders = DevExpress.XtraPrinting.BorderSide.None
Me.XrTableCell24.Dpi = 254.0!
Me.XrTableCell24.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.XrTableCell24.ForeColor = System.Drawing.Color.Black
Me.XrTableCell24.Multiline = True
Me.XrTableCell24.Name = "XrTableCell24"
Me.XrTableCell24.StyleName = "DetailCaption1"
Me.XrTableCell24.StylePriority.UseBackColor = False
Me.XrTableCell24.StylePriority.UseBorderColor = False
Me.XrTableCell24.StylePriority.UseBorders = False
Me.XrTableCell24.StylePriority.UseFont = False
Me.XrTableCell24.StylePriority.UseForeColor = False
Me.XrTableCell24.Weight = 0.2656113622128245R
'
'XrTableCell25
'
Me.XrTableCell25.BackColor = System.Drawing.Color.White
Me.XrTableCell25.BorderColor = System.Drawing.Color.Empty
Me.XrTableCell25.Borders = DevExpress.XtraPrinting.BorderSide.None
Me.XrTableCell25.Dpi = 254.0!
Me.XrTableCell25.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.XrTableCell25.ForeColor = System.Drawing.Color.Black
Me.XrTableCell25.Multiline = True
Me.XrTableCell25.Name = "XrTableCell25"
Me.XrTableCell25.StyleName = "DetailCaption1"
Me.XrTableCell25.StylePriority.UseBackColor = False
Me.XrTableCell25.StylePriority.UseBorderColor = False
Me.XrTableCell25.StylePriority.UseBorders = False
Me.XrTableCell25.StylePriority.UseFont = False
Me.XrTableCell25.StylePriority.UseForeColor = False
Me.XrTableCell25.Text = "Zertifizierung"
Me.XrTableCell25.Weight = 0.11578821158083684R
'
'XrTableCell26
'
Me.XrTableCell26.BackColor = System.Drawing.Color.White
Me.XrTableCell26.BorderColor = System.Drawing.Color.Empty
Me.XrTableCell26.Borders = DevExpress.XtraPrinting.BorderSide.None
Me.XrTableCell26.Dpi = 254.0!
Me.XrTableCell26.ExpressionBindings.AddRange(New DevExpress.XtraReports.UI.ExpressionBinding() {New DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[Envelope].[CertificationType]")})
Me.XrTableCell26.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.XrTableCell26.ForeColor = System.Drawing.Color.Black
Me.XrTableCell26.Multiline = True
Me.XrTableCell26.Name = "XrTableCell26"
Me.XrTableCell26.StyleName = "DetailCaption1"
Me.XrTableCell26.StylePriority.UseBackColor = False
Me.XrTableCell26.StylePriority.UseBorderColor = False
Me.XrTableCell26.StylePriority.UseBorders = False
Me.XrTableCell26.StylePriority.UseFont = False
Me.XrTableCell26.StylePriority.UseForeColor = False
Me.XrTableCell26.Text = "XrTableCell26"
Me.XrTableCell26.Weight = 0.38280260446913161R
'
'GroupHeader1
'
Me.GroupHeader1.Controls.AddRange(New DevExpress.XtraReports.UI.XRControl() {Me.table1})
Me.GroupHeader1.Dpi = 254.0!
Me.GroupHeader1.GroupUnion = DevExpress.XtraReports.UI.GroupUnion.WithFirstDetail
Me.GroupHeader1.HeightF = 71.12!
Me.GroupHeader1.Name = "GroupHeader1"
'
'table1
'
Me.table1.Dpi = 254.0!
Me.table1.LocationFloat = New DevExpress.Utils.PointFloat(0!, 0!)
Me.table1.Name = "table1"
Me.table1.Rows.AddRange(New DevExpress.XtraReports.UI.XRTableRow() {Me.tableRow1})
Me.table1.SizeF = New System.Drawing.SizeF(1900.0!, 71.12!)
'
'tableRow1
'
Me.tableRow1.Cells.AddRange(New DevExpress.XtraReports.UI.XRTableCell() {Me.tableCell1, Me.tableCell2, Me.tableCell3})
Me.tableRow1.Dpi = 254.0!
Me.tableRow1.Name = "tableRow1"
Me.tableRow1.Weight = 1.0R
'
'tableCell1
'
Me.tableCell1.BackColor = System.Drawing.Color.FromArgb(CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer))
Me.tableCell1.BorderColor = System.Drawing.Color.FromArgb(CType(CType(165, Byte), Integer), CType(CType(36, Byte), Integer), CType(CType(49, Byte), Integer))
Me.tableCell1.Borders = DevExpress.XtraPrinting.BorderSide.Bottom
Me.tableCell1.BorderWidth = 1.0!
Me.tableCell1.Dpi = 254.0!
Me.tableCell1.ForeColor = System.Drawing.Color.Black
Me.tableCell1.Name = "tableCell1"
Me.tableCell1.StyleName = "DetailCaption1"
Me.tableCell1.StylePriority.UseBackColor = False
Me.tableCell1.StylePriority.UseBorderColor = False
Me.tableCell1.StylePriority.UseBorders = False
Me.tableCell1.StylePriority.UseBorderWidth = False
Me.tableCell1.StylePriority.UseForeColor = False
Me.tableCell1.Text = "Ereignis"
Me.tableCell1.Weight = 0.51726482588176181R
'
'tableCell2
'
Me.tableCell2.BackColor = System.Drawing.Color.FromArgb(CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer))
Me.tableCell2.BorderColor = System.Drawing.Color.FromArgb(CType(CType(165, Byte), Integer), CType(CType(36, Byte), Integer), CType(CType(49, Byte), Integer))
Me.tableCell2.Borders = DevExpress.XtraPrinting.BorderSide.Bottom
Me.tableCell2.BorderWidth = 1.0!
Me.tableCell2.Dpi = 254.0!
Me.tableCell2.ForeColor = System.Drawing.Color.Black
Me.tableCell2.Name = "tableCell2"
Me.tableCell2.StyleName = "DetailCaption1"
Me.tableCell2.StylePriority.UseBackColor = False
Me.tableCell2.StylePriority.UseBorderColor = False
Me.tableCell2.StylePriority.UseBorders = False
Me.tableCell2.StylePriority.UseBorderWidth = False
Me.tableCell2.StylePriority.UseForeColor = False
Me.tableCell2.Text = "Benutzer"
Me.tableCell2.Weight = 0.45140669898958585R
'
'tableCell3
'
Me.tableCell3.BackColor = System.Drawing.Color.FromArgb(CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer))
Me.tableCell3.BorderColor = System.Drawing.Color.FromArgb(CType(CType(165, Byte), Integer), CType(CType(36, Byte), Integer), CType(CType(49, Byte), Integer))
Me.tableCell3.Borders = DevExpress.XtraPrinting.BorderSide.Bottom
Me.tableCell3.BorderWidth = 1.0!
Me.tableCell3.Dpi = 254.0!
Me.tableCell3.ForeColor = System.Drawing.Color.Black
Me.tableCell3.Name = "tableCell3"
Me.tableCell3.StyleName = "DetailCaption1"
Me.tableCell3.StylePriority.UseBackColor = False
Me.tableCell3.StylePriority.UseBorderColor = False
Me.tableCell3.StylePriority.UseBorders = False
Me.tableCell3.StylePriority.UseBorderWidth = False
Me.tableCell3.StylePriority.UseForeColor = False
Me.tableCell3.Text = "Zeitstempel"
Me.tableCell3.Weight = 0.22479583469004233R
'
'Detail
'
Me.Detail.Controls.AddRange(New DevExpress.XtraReports.UI.XRControl() {Me.table2})
Me.Detail.Dpi = 254.0!
Me.Detail.HeightF = 86.174!
Me.Detail.HierarchyPrintOptions.Indent = 50.8!
Me.Detail.Name = "Detail"
'
'table2
'
Me.table2.Dpi = 254.0!
Me.table2.LocationFloat = New DevExpress.Utils.PointFloat(0!, 0!)
Me.table2.Name = "table2"
Me.table2.Rows.AddRange(New DevExpress.XtraReports.UI.XRTableRow() {Me.tableRow2})
Me.table2.SizeF = New System.Drawing.SizeF(1900.0!, 63.42!)
'
'tableRow2
'
Me.tableRow2.Cells.AddRange(New DevExpress.XtraReports.UI.XRTableCell() {Me.tableCell4, Me.tableCell5, Me.tableCell6})
Me.tableRow2.Dpi = 254.0!
Me.tableRow2.Name = "tableRow2"
Me.tableRow2.Weight = 11.683999633789062R
'
'tableCell4
'
Me.tableCell4.Borders = DevExpress.XtraPrinting.BorderSide.None
Me.tableCell4.Dpi = 254.0!
Me.tableCell4.ExpressionBindings.AddRange(New DevExpress.XtraReports.UI.ExpressionBinding() {New DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[ItemStatusTranslated]")})
Me.tableCell4.Name = "tableCell4"
Me.tableCell4.StyleName = "DetailData1"
Me.tableCell4.StylePriority.UseBorders = False
Me.tableCell4.Weight = 0.51726482142156094R
'
'tableCell5
'
Me.tableCell5.Dpi = 254.0!
Me.tableCell5.ExpressionBindings.AddRange(New DevExpress.XtraReports.UI.ExpressionBinding() {New DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[ItemUserReference]")})
Me.tableCell5.Name = "tableCell5"
Me.tableCell5.StyleName = "DetailData1"
Me.tableCell5.Weight = 0.45140669932916544R
'
'tableCell6
'
Me.tableCell6.Dpi = 254.0!
Me.tableCell6.ExpressionBindings.AddRange(New DevExpress.XtraReports.UI.ExpressionBinding() {New DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[ItemDate]")})
Me.tableCell6.Name = "tableCell6"
Me.tableCell6.StyleName = "DetailData1"
Me.tableCell6.StylePriority.UseTextAlignment = False
Me.tableCell6.TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleRight
Me.tableCell6.Weight = 0.22479581593269077R
'
'Title
'
Me.Title.BackColor = System.Drawing.Color.Transparent
Me.Title.BorderColor = System.Drawing.Color.Black
Me.Title.Borders = DevExpress.XtraPrinting.BorderSide.None
Me.Title.BorderWidth = 1.0!
Me.Title.Font = New System.Drawing.Font("Arial", 14.25!)
Me.Title.ForeColor = System.Drawing.Color.FromArgb(CType(CType(75, Byte), Integer), CType(CType(75, Byte), Integer), CType(CType(75, Byte), Integer))
Me.Title.Name = "Title"
Me.Title.Padding = New DevExpress.XtraPrinting.PaddingInfo(15, 15, 0, 0, 254.0!)
'
'DetailCaption1
'
Me.DetailCaption1.BackColor = System.Drawing.Color.FromArgb(CType(CType(75, Byte), Integer), CType(CType(75, Byte), Integer), CType(CType(75, Byte), Integer))
Me.DetailCaption1.BorderColor = System.Drawing.Color.White
Me.DetailCaption1.Borders = DevExpress.XtraPrinting.BorderSide.Left
Me.DetailCaption1.BorderWidth = 2.0!
Me.DetailCaption1.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Bold)
Me.DetailCaption1.ForeColor = System.Drawing.Color.White
Me.DetailCaption1.Name = "DetailCaption1"
Me.DetailCaption1.Padding = New DevExpress.XtraPrinting.PaddingInfo(15, 15, 0, 0, 254.0!)
Me.DetailCaption1.TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleLeft
'
'DetailData1
'
Me.DetailData1.BorderColor = System.Drawing.Color.Transparent
Me.DetailData1.Borders = DevExpress.XtraPrinting.BorderSide.Left
Me.DetailData1.BorderWidth = 2.0!
Me.DetailData1.Font = New System.Drawing.Font("Arial", 8.25!)
Me.DetailData1.ForeColor = System.Drawing.Color.Black
Me.DetailData1.Name = "DetailData1"
Me.DetailData1.Padding = New DevExpress.XtraPrinting.PaddingInfo(15, 15, 0, 0, 254.0!)
Me.DetailData1.TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleLeft
'
'DetailData3_Odd
'
Me.DetailData3_Odd.BackColor = System.Drawing.Color.FromArgb(CType(CType(231, Byte), Integer), CType(CType(231, Byte), Integer), CType(CType(231, Byte), Integer))
Me.DetailData3_Odd.BorderColor = System.Drawing.Color.Transparent
Me.DetailData3_Odd.Borders = DevExpress.XtraPrinting.BorderSide.None
Me.DetailData3_Odd.BorderWidth = 1.0!
Me.DetailData3_Odd.Font = New System.Drawing.Font("Arial", 8.25!)
Me.DetailData3_Odd.ForeColor = System.Drawing.Color.Black
Me.DetailData3_Odd.Name = "DetailData3_Odd"
Me.DetailData3_Odd.Padding = New DevExpress.XtraPrinting.PaddingInfo(15, 15, 0, 0, 254.0!)
Me.DetailData3_Odd.TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleLeft
'
'PageInfo
'
Me.PageInfo.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Bold)
Me.PageInfo.ForeColor = System.Drawing.Color.FromArgb(CType(CType(75, Byte), Integer), CType(CType(75, Byte), Integer), CType(CType(75, Byte), Integer))
Me.PageInfo.Name = "PageInfo"
Me.PageInfo.Padding = New DevExpress.XtraPrinting.PaddingInfo(15, 15, 0, 0, 254.0!)
'
'GalleryDropDown1
'
Me.GalleryDropDown1.Manager = Nothing
Me.GalleryDropDown1.Name = "GalleryDropDown1"
'
'ObjectDataSource1
'
Me.ObjectDataSource1.DataMember = "Items"
'Me.ObjectDataSource1.DataSource = GetType(EnvelopeGenerator.CommonServices.ReportSource)
Me.ObjectDataSource1.Name = "ObjectDataSource1"
'
'rptEnvelopeHistory
'
Me.Bands.AddRange(New DevExpress.XtraReports.UI.Band() {Me.TopMargin, Me.BottomMargin, Me.ReportHeader, Me.GroupHeader1, Me.Detail})
Me.ComponentStorage.AddRange(New System.ComponentModel.IComponent() {Me.ObjectDataSource1})
Me.DataSource = Me.ObjectDataSource1
Me.Dpi = 254.0!
Me.Font = New System.Drawing.Font("Arial", 9.75!)
Me.Margins = New System.Drawing.Printing.Margins(100, 100, 191, 100)
Me.PageHeight = 2970
Me.PageWidth = 2100
Me.PaperKind = System.Drawing.Printing.PaperKind.A4
Me.ReportUnit = DevExpress.XtraReports.UI.ReportUnit.TenthsOfAMillimeter
Me.SnapGridSize = 25.0!
Me.StyleSheet.AddRange(New DevExpress.XtraReports.UI.XRControlStyle() {Me.Title, Me.DetailCaption1, Me.DetailData1, Me.DetailData3_Odd, Me.PageInfo})
Me.Version = "21.2"
Me.Watermark.ImageSource = New DevExpress.XtraPrinting.Drawing.ImageSource("img", resources.GetString("rptEnvelopeHistory.Watermark.ImageSource"))
Me.Watermark.ImageTransparency = 220
CType(Me.XrTable3, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.table1, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.table2, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.GalleryDropDown1, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.ObjectDataSource1, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me, System.ComponentModel.ISupportInitialize).EndInit()
End Sub
Friend WithEvents TopMargin As DevExpress.XtraReports.UI.TopMarginBand
Friend WithEvents BottomMargin As DevExpress.XtraReports.UI.BottomMarginBand
Friend WithEvents pageInfo1 As DevExpress.XtraReports.UI.XRPageInfo
Friend WithEvents pageInfo2 As DevExpress.XtraReports.UI.XRPageInfo
Friend WithEvents ReportHeader As DevExpress.XtraReports.UI.ReportHeaderBand
Friend WithEvents label1 As DevExpress.XtraReports.UI.XRLabel
Friend WithEvents GroupHeader1 As DevExpress.XtraReports.UI.GroupHeaderBand
Friend WithEvents table1 As DevExpress.XtraReports.UI.XRTable
Friend WithEvents tableRow1 As DevExpress.XtraReports.UI.XRTableRow
Friend WithEvents tableCell1 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents tableCell2 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents tableCell3 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents Detail As DevExpress.XtraReports.UI.DetailBand
Friend WithEvents table2 As DevExpress.XtraReports.UI.XRTable
Friend WithEvents tableRow2 As DevExpress.XtraReports.UI.XRTableRow
Friend WithEvents tableCell4 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents tableCell5 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents tableCell6 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents ObjectDataSource1 As DevExpress.DataAccess.ObjectBinding.ObjectDataSource
Friend WithEvents Title As DevExpress.XtraReports.UI.XRControlStyle
Friend WithEvents DetailCaption1 As DevExpress.XtraReports.UI.XRControlStyle
Friend WithEvents DetailData1 As DevExpress.XtraReports.UI.XRControlStyle
Friend WithEvents DetailData3_Odd As DevExpress.XtraReports.UI.XRControlStyle
Friend WithEvents PageInfo As DevExpress.XtraReports.UI.XRControlStyle
Friend WithEvents XrLabel1 As DevExpress.XtraReports.UI.XRLabel
Friend WithEvents XrTable3 As DevExpress.XtraReports.UI.XRTable
Friend WithEvents XrTableRow8 As DevExpress.XtraReports.UI.XRTableRow
Friend WithEvents XrTableCell13 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents XrTableCell15 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents XrTableRow9 As DevExpress.XtraReports.UI.XRTableRow
Friend WithEvents XrTableCell14 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents XrTableCell17 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents XrTableCell16 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents XrTableCell18 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents XrTableRow10 As DevExpress.XtraReports.UI.XRTableRow
Friend WithEvents XrTableCell19 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents XrTableCell20 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents XrTableCell21 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents XrTableCell22 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents XrTableRow11 As DevExpress.XtraReports.UI.XRTableRow
Friend WithEvents XrTableCell23 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents XrTableCell24 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents XrTableCell25 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents XrTableCell26 As DevExpress.XtraReports.UI.XRTableCell
Friend WithEvents GalleryDropDown1 As DevExpress.XtraBars.Ribbon.GalleryDropDown
End Class

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
Public Class rptEnvelopeHistory
End Class

View File

@@ -1,8 +0,0 @@
namespace EnvelopeGenerator.Application.Common.Configurations;
/// <summary>
///
/// </summary>
public class DbTriggerParams : Dictionary<string, ICollection<string>>
{
}

View File

@@ -0,0 +1,12 @@
namespace EnvelopeGenerator.Application.Common.Configurations;
/// <summary>
///
/// </summary>
public class GdPictureParams
{
/// <summary>
///
/// </summary>
public string License { get; set; } = null!;
}

View File

@@ -0,0 +1,78 @@
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 int ConcurrencyLimit { get; set; } = 5;
/// <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;
}

View File

@@ -0,0 +1,73 @@
namespace EnvelopeGenerator.Application.Common.Dto;
/// <summary>
///
/// </summary>
public record AnnotationCreateDto
{
/// <summary>
///
/// </summary>
public int ElementId { get; init; }
/// <summary>
///
/// </summary>
public string Name { get; init; } = null!;
/// <summary>
///
/// </summary>
public string Value { get; init; } = null!;
/// <summary>
///
/// </summary>
public string Type { get; init; } = null!;
/// <summary>
///
/// </summary>
public double? X { get; init; }
/// <summary>
///
/// </summary>
public double? Y { get; init; }
/// <summary>
///
/// </summary>
public double? Width { get; init; }
/// <summary>
///
/// </summary>
public double? Height { get; init; }
}
/// <summary>
///
/// </summary>
public record AnnotationDto : AnnotationCreateDto
{
/// <summary>
///
/// </summary>
public long Id { get; init; }
/// <summary>
///
/// </summary>
public DateTime AddedWhen { get; init; }
/// <summary>
///
/// </summary>
public DateTime? ChangedWhen { get; init; }
/// <summary>
///
/// </summary>
public string? ChangedWho { get; init; }
}

View File

@@ -0,0 +1,44 @@
namespace EnvelopeGenerator.Application.Common.Dto;
/// <summary>
///
/// </summary>
public record EnvelopeReportDto
{
/// <summary>
///
/// </summary>
public int EnvelopeId { get; set; }
// --- HEAD ---
/// <summary>
///
/// </summary>
public string HeadUuid { get; set; } = null!;
/// <summary>
///
/// </summary>
public string EnvelopeTitle { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string HeadMessage { get; set; } = null!;
// --- POSITIONS ---
/// <summary>
///
/// </summary>
public int ItemStatus { get; set; }
/// <summary>
///
/// </summary>
public DateTime? ItemDate { get; set; }
/// <summary>
///
/// </summary>
public string ItemUserReference { get; set; } = null!;
}

View File

@@ -35,6 +35,9 @@ public class MappingProfile : Profile
CreateMap<EnvelopeType, EnvelopeTypeDto>();
CreateMap<Domain.Entities.Receiver, ReceiverDto>();
CreateMap<Domain.Entities.EnvelopeReceiverReadOnly, EnvelopeReceiverReadOnlyDto>();
CreateMap<ElementAnnotation, AnnotationDto>();
CreateMap<ThirdPartyModule, ThirdPartyModuleDto>();
CreateMap<EnvelopeReport, EnvelopeReportDto>();
// DTO to Entity mappings
CreateMap<ConfigDto, Config>();
@@ -50,6 +53,8 @@ public class MappingProfile : Profile
CreateMap<ReceiverDto, Domain.Entities.Receiver>().ForMember(rcv => rcv.EnvelopeReceivers, rcvReadDto => rcvReadDto.Ignore());
CreateMap<EnvelopeReceiverReadOnlyCreateDto, Domain.Entities.EnvelopeReceiverReadOnly>();
CreateMap<EnvelopeReceiverReadOnlyUpdateDto, Domain.Entities.EnvelopeReceiverReadOnly>();
CreateMap<AnnotationCreateDto, ElementAnnotation>()
.ForMember(dest => dest.AddedWhen, opt => opt.MapFrom(_ => DateTime.UtcNow));
// Messaging mappings
// for GTX messaging

View File

@@ -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; }
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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; }
}

View File

@@ -0,0 +1,7 @@
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
/// <summary>
///
/// </summary>
/// <param name="Points"></param>
public record Lines(List<List<List<float>>> Points);

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc;
using EnvelopeGenerator.Domain.Interfaces;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.Application.Common.Dto;
@@ -6,7 +7,7 @@ namespace EnvelopeGenerator.Application.Common.Dto;
/// Data Transfer Object representing a positioned element assigned to a document receiver.
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
public class SignatureDto
public class SignatureDto : ISignature
{
/// <summary>
/// Gets or sets the unique identifier of the element.

View File

@@ -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; }
}

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,18 @@
using System.Text.Json;
namespace EnvelopeGenerator.Application.Common.Extensions;
/// <summary>
///
/// </summary>
public static class JsonExtensions
{
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
/// <param name="options"></param>
/// <returns></returns>
public static string ToJson(this object obj, JsonSerializerOptions? options = null)
=> JsonSerializer.Serialize(obj, options);
}

View File

@@ -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;
}
}

View File

@@ -1,14 +1,30 @@
using OtpNet;
namespace EnvelopeGenerator.Application.Common.Extensions
namespace EnvelopeGenerator.Application.Common.Extensions;
/// <summary>
///
/// </summary>
public static class StringExtension
{
public static class StringExtension
/// <summary>
///
/// </summary>
/// <param name="totp"></param>
/// <param name="secret"></param>
/// <returns></returns>
public static bool IsValidTotp(this string totp, string secret)
{
public static bool IsValidTotp(this string totp, string secret)
{
var secret_bytes = Base32Encoding.ToBytes(secret);
var secret_totp = new Totp(secret_bytes);
return secret_totp.VerifyTotp(totp, out _, VerificationWindow.RfcSpecifiedNetworkDelay);
}
var secret_bytes = Base32Encoding.ToBytes(secret);
var secret_totp = new Totp(secret_bytes);
return secret_totp.VerifyTotp(totp, out _, VerificationWindow.RfcSpecifiedNetworkDelay);
}
/// <summary>
///
/// </summary>
/// <param name="seperator"></param>
/// <param name="values"></param>
/// <returns></returns>
public static string Join(this IEnumerable<string> values, string seperator) => string.Join(seperator, values);
}

View File

@@ -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; }
}

View File

@@ -1,7 +1,7 @@
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Repositories;
namespace EnvelopeGenerator.Application.Common.Interfaces.Repositories;
/// <summary>
///

View File

@@ -1,7 +1,7 @@
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Repositories;
namespace EnvelopeGenerator.Application.Common.Interfaces.Repositories;
/// <summary>
///
/// </summary>

View File

@@ -1,7 +1,7 @@
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Repositories;
namespace EnvelopeGenerator.Application.Common.Interfaces.Repositories;
/// <summary>
///

View File

@@ -2,7 +2,7 @@
using EnvelopeGenerator.Domain.Constants;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Repositories;
namespace EnvelopeGenerator.Application.Common.Interfaces.Repositories;
/// <summary>
///

View File

@@ -1,7 +1,7 @@
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Repositories;
namespace EnvelopeGenerator.Application.Common.Interfaces.Repositories;
/// <summary>
///

View File

@@ -2,7 +2,7 @@
using EnvelopeGenerator.Domain.Constants;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Repositories;
namespace EnvelopeGenerator.Application.Common.Interfaces.Repositories;
/// <summary>
///

View File

@@ -1,7 +1,7 @@
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Repositories;
namespace EnvelopeGenerator.Application.Common.Interfaces.Repositories;
/// <summary>
///

View File

@@ -3,7 +3,7 @@ using EnvelopeGenerator.Application.Envelopes.Queries;
using EnvelopeGenerator.Domain.Constants;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Repositories;
namespace EnvelopeGenerator.Application.Common.Interfaces.Repositories;
/// <summary>
///

View File

@@ -2,7 +2,7 @@
using EnvelopeGenerator.Domain.Constants;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Repositories;
namespace EnvelopeGenerator.Application.Common.Interfaces.Repositories;
/// <summary>
///

View File

@@ -1,7 +1,7 @@
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Repositories;
namespace EnvelopeGenerator.Application.Common.Interfaces.Repositories;
/// <summary>
///

View File

@@ -1,7 +1,7 @@
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Repositories;
namespace EnvelopeGenerator.Application.Common.Interfaces.Repositories;
/// <summary>
///

View File

@@ -1,6 +1,6 @@
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.SQLExecutor;
namespace EnvelopeGenerator.Application.Common.Interfaces.SQLExecutor;
/// <summary>
///

View File

@@ -1,7 +1,7 @@
using Dapper;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.SQLExecutor;
namespace EnvelopeGenerator.Application.Common.Interfaces.SQLExecutor;
/// <summary>
///

View File

@@ -1,6 +1,6 @@
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.SQLExecutor;
namespace EnvelopeGenerator.Application.Common.Interfaces.SQLExecutor;
/// <summary>
///

View File

@@ -1,4 +1,4 @@
namespace EnvelopeGenerator.Application.Interfaces.SQLExecutor;
namespace EnvelopeGenerator.Application.Common.Interfaces.SQLExecutor;
/// <summary>
/// Provides methods for executing common queries on a given entity type.

View File

@@ -1,4 +1,4 @@
namespace EnvelopeGenerator.Application.Interfaces.SQLExecutor;
namespace EnvelopeGenerator.Application.Common.Interfaces.SQLExecutor;
/// <summary>
/// Represents a raw SQL query contract.

View File

@@ -1,4 +1,4 @@
namespace EnvelopeGenerator.Application.Interfaces.SQLExecutor;
namespace EnvelopeGenerator.Application.Common.Interfaces.SQLExecutor;
/// <summary>
/// Defines methods for executing raw SQL queries or custom SQL query classes and returning query executors for further operations.

View File

@@ -1,6 +1,6 @@
using Dapper;
namespace EnvelopeGenerator.Application.Interfaces.SQLExecutor;
namespace EnvelopeGenerator.Application.Common.Interfaces.SQLExecutor;
/// <summary>
///

View File

@@ -1,6 +1,6 @@
using OtpNet;
namespace EnvelopeGenerator.Application.Interfaces.Services;
namespace EnvelopeGenerator.Application.Common.Interfaces.Services;
/// <summary>
///

View File

@@ -3,7 +3,7 @@ using DigitalData.Core.Abstraction.Application.DTO;
using EnvelopeGenerator.Application.Common.Dto;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Services;
namespace EnvelopeGenerator.Application.Common.Interfaces.Services;
/// <summary>
///

View File

@@ -2,7 +2,7 @@
using EnvelopeGenerator.Application.Common.Dto;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Services;
namespace EnvelopeGenerator.Application.Common.Interfaces.Services;
/// <summary>
///

View File

@@ -1,7 +1,7 @@
using DigitalData.Core.Abstraction.Application;
using EnvelopeGenerator.Application.Common.Dto;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Services;
namespace EnvelopeGenerator.Application.Common.Interfaces.Services;
/// <summary>
///

View File

@@ -4,7 +4,7 @@ using EnvelopeGenerator.Application.Common.Dto;
using EnvelopeGenerator.Domain.Constants;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Services;
namespace EnvelopeGenerator.Application.Common.Interfaces.Services;
/// <summary>
///

View File

@@ -2,7 +2,7 @@
using EnvelopeGenerator.Application.Common.Dto;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Services;
namespace EnvelopeGenerator.Application.Common.Interfaces.Services;
/// <summary>
///

View File

@@ -5,7 +5,7 @@ using EnvelopeGenerator.Application.Common.Dto.Receiver;
using EnvelopeGenerator.Domain.Constants;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Services;
namespace EnvelopeGenerator.Application.Common.Interfaces.Services;
/// <summary>
///

View File

@@ -4,7 +4,7 @@ using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiverReadOnly;
using EnvelopeGenerator.Domain.Constants;
namespace EnvelopeGenerator.Application.Interfaces.Services;
namespace EnvelopeGenerator.Application.Common.Interfaces.Services;
/// <summary>
///

View File

@@ -2,7 +2,7 @@
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiverReadOnly;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Services;
namespace EnvelopeGenerator.Application.Common.Interfaces.Services;
/// <summary>
///

View File

@@ -10,7 +10,7 @@ using EnvelopeGenerator.Domain;
using EnvelopeGenerator.Domain.Constants;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Services;
namespace EnvelopeGenerator.Application.Common.Interfaces.Services;
/// <summary>
///

View File

@@ -4,7 +4,7 @@ using EnvelopeGenerator.Application.Common.Dto;
using EnvelopeGenerator.Domain.Constants;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Services;
namespace EnvelopeGenerator.Application.Common.Interfaces.Services;
/// <summary>
///

View File

@@ -1,7 +1,7 @@
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
using EnvelopeGenerator.Application.Common.Dto.Messaging;
namespace EnvelopeGenerator.Application.Interfaces.Services;
namespace EnvelopeGenerator.Application.Common.Interfaces.Services;
/// <summary>
///

View File

@@ -2,7 +2,7 @@
using EnvelopeGenerator.Application.Common.Dto;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Services;
namespace EnvelopeGenerator.Application.Common.Interfaces.Services;
/// <summary>
///

View File

@@ -4,7 +4,7 @@ using EnvelopeGenerator.Application.Common.Dto.Receiver;
using EnvelopeGenerator.Application.Receivers.Commands;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Interfaces.Services;
namespace EnvelopeGenerator.Application.Common.Interfaces.Services;
/// <summary>
///

View File

@@ -1,6 +1,6 @@
using EnvelopeGenerator.Application.Common.Dto.Messaging;
namespace EnvelopeGenerator.Application.Interfaces.Services;
namespace EnvelopeGenerator.Application.Common.Interfaces.Services;
//TODO: move to DigitalData.Core
/// <summary>

View File

@@ -1,11 +1,20 @@
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
using EnvelopeGenerator.Application.Common.Dto;
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
using EnvelopeGenerator.Application.Common.Extensions;
using EnvelopeGenerator.Application.Common.Notifications.RemoveSignature;
using EnvelopeGenerator.Domain.Constants;
using MediatR;
using Newtonsoft.Json;
using System.Dynamic;
namespace EnvelopeGenerator.Application.Common.Notifications.DocSigned;
/// <summary>
///
/// </summary>
/// <param name="Instant"></param>
/// <param name="Structured"></param>
public record PsPdfKitAnnotation(ExpandoObject Instant, IEnumerable<AnnotationCreateDto> Structured);
/// <summary>
///
/// </summary>
@@ -15,7 +24,7 @@ public record DocSignedNotification(EnvelopeReceiverDto Original) : EnvelopeRece
/// <summary>
///
/// </summary>
public required ExpandoObject Annotations { get; init; }
public PsPdfKitAnnotation PsPdfKitAnnotation { get; init; } = null!;
/// <summary>
///
@@ -27,7 +36,7 @@ public record DocSignedNotification(EnvelopeReceiverDto Original) : EnvelopeRece
/// </summary>
public string EmailAddress => Receiver?.EmailAddress
?? throw new InvalidOperationException($"Receiver is null." +
$"DocSignedNotification:\n{JsonConvert.SerializeObject(this, Format.Json.ForDiagnostics)}");
$"DocSignedNotification:\n{this.ToJson(Format.Json.ForDiagnostics)}");
}
/// <summary>
@@ -39,17 +48,41 @@ public static class DocSignedNotificationExtensions
/// Converts an <see cref="EnvelopeReceiverDto"/> to a <see cref="DocSignedNotification"/>.
/// </summary>
/// <param name="dto">The DTO to convert.</param>
/// <param name="annotations"></param>
/// <param name="psPdfKitAnnotation"></param>
/// <returns>A new <see cref="DocSignedNotification"/> instance.</returns>
public static DocSignedNotification ToDocSignedNotification(this EnvelopeReceiverDto dto, ExpandoObject annotations)
=> new(dto) { Annotations = annotations };
public static DocSignedNotification ToDocSignedNotification(this EnvelopeReceiverDto dto, PsPdfKitAnnotation psPdfKitAnnotation)
=> new(dto) { PsPdfKitAnnotation = psPdfKitAnnotation };
/// <summary>
/// Asynchronously converts a <see cref="Task{EnvelopeReceiverDto}"/> to a <see cref="DocSignedNotification"/>.
///
/// </summary>
/// <param name="dtoTask">The task that returns the DTO to convert.</param>
/// <param name="annotations"></param>
/// <returns>A task that represents the asynchronous conversion operation.</returns>
public static async Task<DocSignedNotification?> ToDocSignedNotification(this Task<EnvelopeReceiverDto?> dtoTask, ExpandoObject annotations)
=> await dtoTask is EnvelopeReceiverDto dto ? new(dto) { Annotations = annotations } : null;
/// <param name="dtoTask"></param>
/// <param name="psPdfKitAnnotation"></param>
/// <returns></returns>
public static async Task<DocSignedNotification?> ToDocSignedNotification(this Task<EnvelopeReceiverDto?> dtoTask, PsPdfKitAnnotation psPdfKitAnnotation)
=> await dtoTask is EnvelopeReceiverDto dto ? new(dto) { PsPdfKitAnnotation = psPdfKitAnnotation } : null;
/// <summary>
///
/// </summary>
/// <param name="publisher"></param>
/// <param name="notification"></param>
/// <param name="cancel"></param>
/// <returns></returns>
public static async Task PublishSafely(this IPublisher publisher, DocSignedNotification notification, CancellationToken cancel = default)
{
try
{
await publisher.Publish(notification, cancel);
}
catch (Exception)
{
await publisher.Publish(new RemoveSignatureNotification()
{
EnvelopeId = notification.EnvelopeId,
ReceiverId = notification.ReceiverId
}, cancel);
throw;
}
}
}

View File

@@ -1,8 +1,6 @@
using EnvelopeGenerator.Application.Common.Notifications.DocSigned;
using EnvelopeGenerator.Application.DocStatus.Commands;
using EnvelopeGenerator.Domain.Constants;
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
using MediatR;
using Newtonsoft.Json;
namespace EnvelopeGenerator.Application.Common.Notifications.DocSigned.Handlers;
@@ -11,15 +9,18 @@ namespace EnvelopeGenerator.Application.Common.Notifications.DocSigned.Handlers;
/// </summary>
public class AnnotationHandler : INotificationHandler<DocSignedNotification>
{
private readonly ISender _sender;
/// <summary>
///
/// </summary>
private readonly IRepository<ElementAnnotation> _repo;
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
public AnnotationHandler(ISender sender)
/// <param name="repository"></param>
public AnnotationHandler(IRepository<ElementAnnotation> repository)
{
_sender = sender;
_repo = repository;
}
/// <summary>
@@ -28,13 +29,6 @@ public class AnnotationHandler : INotificationHandler<DocSignedNotification>
/// <param name="notification"></param>
/// <param name="cancel"></param>
/// <returns></returns>
public async Task Handle(DocSignedNotification notification, CancellationToken cancel)
{
await _sender.Send(new SaveDocStatusCommand()
{
Envelope = new() { Id = notification.EnvelopeId },
Receiver = new() { Id = notification.ReceiverId},
Value = JsonConvert.SerializeObject(notification.Annotations, Format.Json.ForAnnotations)
}, cancel);
}
public Task Handle(DocSignedNotification notification, CancellationToken cancel)
=> _repo.CreateAsync(notification.PsPdfKitAnnotation.Structured, cancel);
}

View File

@@ -0,0 +1,39 @@
using EnvelopeGenerator.Application.DocStatus.Commands;
using EnvelopeGenerator.Domain.Constants;
using MediatR;
using System.Text.Json;
namespace EnvelopeGenerator.Application.Common.Notifications.DocSigned.Handlers;
/// <summary>
///
/// </summary>
public class DocStatusHandler : INotificationHandler<DocSignedNotification>
{
private readonly ISender _sender;
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
public DocStatusHandler(ISender sender)
{
_sender = sender;
}
/// <summary>
///
/// </summary>
/// <param name="notification"></param>
/// <param name="cancel"></param>
/// <returns></returns>
public async Task Handle(DocSignedNotification notification, CancellationToken cancel)
{
await _sender.Send(new SaveDocStatusCommand()
{
Envelope = new() { Id = notification.EnvelopeId },
Receiver = new() { Id = notification.ReceiverId},
Value = JsonSerializer.Serialize(notification.PsPdfKitAnnotation.Instant, Format.Json.ForAnnotations)
}, cancel);
}
}

View File

@@ -1,8 +1,7 @@
using EnvelopeGenerator.Application.Common.Notifications.DocSigned;
using EnvelopeGenerator.Application.Common.Extensions;
using EnvelopeGenerator.Application.Histories.Commands;
using EnvelopeGenerator.Domain.Constants;
using MediatR;
using Newtonsoft.Json;
namespace EnvelopeGenerator.Application.Common.Notifications.DocSigned.Handlers;
@@ -30,16 +29,14 @@ public class HistoryHandler : INotificationHandler<DocSignedNotification>
/// <returns></returns>
public async Task Handle(DocSignedNotification notification, CancellationToken cancel)
{
if(notification.Receiver is null)
if (notification.Receiver is null)
throw new InvalidOperationException($"Receiver information is missing in the notification. DocSignedNotification:\n {JsonConvert.SerializeObject(notification, Format.Json.ForDiagnostics)}");
if (notification.Receiver is null)
throw new InvalidOperationException($"Receiver information is missing in the notification. DocSignedNotification:\n {notification.ToJson(Format.Json.ForDiagnostics)}");
await _sender.Send(new CreateHistoryCommand()
{
EnvelopeId = notification.EnvelopeId,
UserReference = notification.Receiver.EmailAddress,
Status = EnvelopeStatus.DocumentSigned,
Comment = JsonConvert.SerializeObject(notification.Annotations, Format.Json.ForAnnotations)
}, cancel);
}
}

View File

@@ -0,0 +1,53 @@
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
using MediatR;
namespace EnvelopeGenerator.Application.Common.Notifications.RemoveSignature.Handlers;
/// <summary>
///
/// </summary>
public class RemoveAnnotationHandler : INotificationHandler<RemoveSignatureNotification>
{
private readonly IRepository<ElementAnnotation> _repo;
/// <summary>
///
/// </summary>
/// <param name="repository"></param>
public RemoveAnnotationHandler(IRepository<ElementAnnotation> repository)
{
_repo = repository;
}
/// <summary>
///
/// </summary>
/// <param name="notification"></param>
/// <param name="cancel"></param>
/// <returns></returns>
public Task Handle(RemoveSignatureNotification notification, CancellationToken cancel)
{
notification.ThrowIfHasNoFilter();
return _repo.DeleteAsync(annots =>
{
// envelope ID filter
if (notification.EnvelopeId is int envelopeId)
annots = annots.Where(annot => annot.Element!.Document.EnvelopeId == envelopeId);
// envelope UUID filter
if (notification.EnvelopeUuid is string envelopeUuid)
annots = annots.Where(annot => annot.Element!.Document.Envelope!.Uuid == envelopeUuid);
// receiver ID
if (notification.ReceiverId is int receiverId)
annots = annots.Where(annot => annot.Element!.ReceiverId == receiverId);
// receiver signature
if (notification.ReceiverSignature is string receiverSignature)
annots = annots.Where(annot => annot.Element!.Receiver!.Signature == receiverSignature);
return annots;
}, cancel);
}
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,53 @@
using AngleSharp.Html;
using DigitalData.Core.Abstraction.Application.Repository;
using MediatR;
namespace EnvelopeGenerator.Application.Common.Notifications.RemoveSignature.Handlers;
/// <summary>
///
/// </summary>
public class RemoveDocStatusHandler : INotificationHandler<RemoveSignatureNotification>
{
private readonly IRepository<Domain.Entities.DocumentStatus> _repo;
/// <summary>
///
/// </summary>
/// <param name="repository"></param>
public RemoveDocStatusHandler(IRepository<Domain.Entities.DocumentStatus> repository)
{
_repo = repository;
}
/// <summary>
///
/// </summary>
/// <param name="notification"></param>
/// <param name="cancel"></param>
/// <returns></returns>
public Task Handle(RemoveSignatureNotification notification, CancellationToken cancel)
{
notification.ThrowIfHasNoFilter();
return _repo.DeleteAsync(statuses =>
{
// envelope ID filter
if (notification.EnvelopeId is int envelopeId)
statuses = statuses.Where(status => status.EnvelopeId == envelopeId);
// envelope UUID filter
if (notification.EnvelopeUuid is string envelopeUuid)
statuses = statuses.Where(status => status.Envelope!.Uuid == envelopeUuid);
// receiver Id filter
if (notification.ReceiverId is int receiverId)
statuses = statuses.Where(status => status.ReceiverId == receiverId);
// receiver signature filter
if (notification.ReceiverSignature is string receiverSignature)
statuses = statuses.Where(status => status.Receiver!.Signature == receiverSignature);
return statuses;
}, cancel);
}
}

View File

@@ -0,0 +1,56 @@
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Application.Common.Extensions;
using EnvelopeGenerator.Domain.Constants;
using MediatR;
namespace EnvelopeGenerator.Application.Common.Notifications.RemoveSignature.Handlers;
/// <summary>
///
/// </summary>
public class RemoveHistoryHandler : INotificationHandler<RemoveSignatureNotification>
{
private readonly IRepository<Domain.Entities.History> _repo;
/// <summary>
///
/// </summary>
/// <param name="repository"></param>
public RemoveHistoryHandler(IRepository<Domain.Entities.History> repository)
{
_repo = repository;
}
/// <summary>
///
/// </summary>
/// <param name="notification"></param>
/// <param name="cancel"></param>
/// <returns></returns>
public Task Handle(RemoveSignatureNotification notification, CancellationToken cancel)
{
notification.ThrowIfHasNoFilter();
return _repo.DeleteAsync(hists =>
{
hists = hists.Where(hist => hist.Status == EnvelopeStatus.DocumentSigned);
// envelope ID filter
if (notification.EnvelopeId is int envelopeId)
hists = hists.Where(hist => hist.EnvelopeId == envelopeId);
// envelope UUID filter
if (notification.EnvelopeUuid is string envelopeUuid)
hists = hists.Where(hist => hist.Envelope!.Uuid == envelopeUuid);
// receiver ID filter
if (notification.ReceiverId is int receiverId)
hists = hists.Where(hist => hist.Receiver!.Id == receiverId);
// receiver signature filter
if (notification.ReceiverSignature is string receiverSignature)
hists = hists.Where(hist => hist.Receiver!.Signature == receiverSignature);
return hists;
}, cancel);
}
}

View File

@@ -0,0 +1,37 @@
using MediatR;
namespace EnvelopeGenerator.Application.Common.Notifications.RemoveSignature;
/// <summary>
///
/// </summary>
/// <param name="EnvelopeId"></param>
/// <param name="ReceiverId"></param>
/// <param name="EnvelopeUuid"></param>
/// <param name="ReceiverSignature"></param>
public record RemoveSignatureNotification(
int? EnvelopeId = null,
int? ReceiverId = null,
string? EnvelopeUuid = null,
string? ReceiverSignature = null
) : INotification
{
/// <summary>
///
/// </summary>
public bool HasFilter =>
EnvelopeId is not null
|| ReceiverId is not null
|| EnvelopeUuid is not null
|| ReceiverSignature is not null;
/// <summary>
///
/// </summary>
/// <exception cref="InvalidOperationException"></exception>
public void ThrowIfHasNoFilter()
{
if (!HasFilter)
throw new InvalidOperationException("At least one filter parameter must be provided.");
}
}

View File

@@ -1,6 +1,7 @@
using DigitalData.Core.Abstraction.Application.Repository;
using DigitalData.EmailProfilerDispatcher.Abstraction.Entities;
using EnvelopeGenerator.Application.Common.Configurations;
using EnvelopeGenerator.Application.Common.Extensions;
using EnvelopeGenerator.Domain.Constants;
using EnvelopeGenerator.Domain.Entities;
using MediatR;
@@ -98,10 +99,10 @@ public abstract class SendMailHandler<TNotification> : INotificationHandler<TNot
var placeHolders = CreatePlaceHolders(notification);
var temp = await TempRepo
.ReadOnly()
.SingleOrDefaultAsync(x => x.Name == notification.TemplateType.ToString(), cancel)
.Where(x => x.Name == notification.TemplateType.ToString())
.SingleOrDefaultAsync(cancel)
?? throw new InvalidOperationException($"Receiver information is missing in the notification." +
$"{typeof(TNotification)}:\n {JsonConvert.SerializeObject(notification, Format.Json.ForDiagnostics)}");
$"{typeof(TNotification)}:\n {notification.ToJson(Format.Json.ForDiagnostics)}");
temp.Subject = ReplacePlaceHolders(temp.Subject, placeHolders, MailParams.Placeholders);
@@ -110,7 +111,7 @@ public abstract class SendMailHandler<TNotification> : INotificationHandler<TNot
var emailOut = new EmailOut
{
EmailAddress = notification.EmailAddress,
EmailBody = TextToHtml(temp.Body),
EmailBody = temp.Body,
EmailSubj = temp.Subject,
AddedWhen = DateTime.UtcNow,
AddedWho = DispatcherParams.AddedWho,
@@ -131,22 +132,4 @@ public abstract class SendMailHandler<TNotification> : INotificationHandler<TNot
text = text.Replace(ph.Key, ph.Value);
return text;
}
private static string TextToHtml(string input)
{
if (string.IsNullOrEmpty(input)) return "";
// HTML encoding special characters
string encoded = System.Net.WebUtility.HtmlEncode(input);
// Convert tabs to &nbsp; (4 non-breaking spaces)
encoded = encoded.Replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
// Convert line breaks to <br />
encoded = encoded.Replace("\r\n", "<br />"); // Windows
encoded = encoded.Replace("\r", "<br />"); // Mac old
encoded = encoded.Replace("\n", "<br />"); // Unix/Linux
return encoded;
}
}

View File

@@ -20,4 +20,14 @@ public record ReceiverQueryBase
/// Eindeutige Signatur des Empfängers
/// </summary>
public virtual string? Signature { get; set; }
/// <summary>
/// Checks whether any of the specified query criteria have a value.
/// </summary>
/// <remarks>
/// This property returns <c>true</c> if at least one of the fields
/// <see cref="Id"/>, <see cref="EmailAddress"/>, or <see cref="Signature"/> is not null.
/// <para>Usage example: The query can be executed only if at least one criterion is specified.</para>
/// </remarks>
public bool HasAnyCriteria => Id is not null || EmailAddress is not null || Signature is not null;
}

View File

@@ -1,7 +1,7 @@
using Dapper;
using EnvelopeGenerator.Application.Interfaces.SQLExecutor;
using DigitalData.Core.Exceptions;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Application.Common.Interfaces.SQLExecutor;
namespace EnvelopeGenerator.Application.Common.SQL;

View File

@@ -1,5 +1,5 @@
using Dapper;
using EnvelopeGenerator.Application.Interfaces.SQLExecutor;
using EnvelopeGenerator.Application.Common.Interfaces.SQLExecutor;
using EnvelopeGenerator.Domain.Entities;
using System.Data;

View File

@@ -1,5 +1,5 @@
using Dapper;
using EnvelopeGenerator.Application.Interfaces.SQLExecutor;
using EnvelopeGenerator.Application.Common.Interfaces.SQLExecutor;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Common.SQL;

View File

@@ -0,0 +1,87 @@
using AutoMapper;
using DigitalData.Core.Abstraction.Application.Repository;
using DigitalData.Core.Exceptions;
using EnvelopeGenerator.Application.Common.Dto;
using EnvelopeGenerator.Domain.Entities;
using MediatR;
using Microsoft.Extensions.Caching.Memory;
namespace EnvelopeGenerator.Application.Configs;
/// <summary>
///
/// </summary>
public class DefaultReadConfigQuery : IRequest<ConfigDto>
{
/// <summary>
///
/// </summary>
public static readonly Guid MemoryCacheKey = Guid.NewGuid();
}
/// <summary>
///
/// </summary>
public static class DefaultReadConfigQueryExtensions
{
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="cancel"></param>
/// <returns></returns>
public static Task<ConfigDto> ReadDefaultConfigAsync(this ISender sender, CancellationToken cancel = default)
=> sender.Send(new DefaultReadConfigQuery(), cancel);
}
/// <summary>
///
/// </summary>
public class DefaultReadConfigQueryHandler : IRequestHandler<DefaultReadConfigQuery, ConfigDto>
{
private readonly IRepository<Config> _repo;
private readonly IMapper _mapper;
private readonly IMemoryCache _cache;
/// <summary>
///
/// </summary>
/// <param name="repo"></param>
/// <param name="mapper"></param>
/// <param name="cache"></param>
public DefaultReadConfigQueryHandler(IRepository<Config> repo, IMapper mapper, IMemoryCache cache)
{
_repo = repo;
_mapper = mapper;
_cache = cache;
}
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="cancel"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<ConfigDto> Handle(DefaultReadConfigQuery request, CancellationToken cancel)
{
var config = await _cache.GetOrCreateAsync(DefaultReadConfigQuery.MemoryCacheKey, async entry =>
{
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5);
var configs = await _repo.GetAllAsync(cancel);
var defaultConfig = configs.FirstOrDefault();
var defaultConfigDto = _mapper.Map<ConfigDto>(defaultConfig);
return defaultConfigDto;
});
if(config is null)
{
_cache.Remove(DefaultReadConfigQuery.MemoryCacheKey);
throw new NotFoundException("No configuration record is found.");
}
return config;
}
}

View File

@@ -1,12 +1,17 @@
using DigitalData.Core.Client;
using EnvelopeGenerator.Application.Common.Configurations;
using EnvelopeGenerator.Application.Interfaces.Services;
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;
using EnvelopeGenerator.Application.Pdf.Behaviors;
namespace EnvelopeGenerator.Application;
@@ -46,7 +51,30 @@ 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<DbTriggerParams>(config.GetSection(nameof(DbTriggerParams)));
#region PDF Burner
services.Configure<PDFBurnerParams>(config.GetSection(nameof(PDFBurnerParams)));
services.AddOptions<GdPictureParams>()
.Configure((GdPictureParams opt, IServiceProvider provider) =>
{
opt.License = config["GdPictureLicenseKey"]
?? provider.GetRequiredService<IMediator>().ReadThirdPartyModuleLicenseAsync("GDPICTURE").GetAwaiter().GetResult()
?? throw new InvalidOperationException($"License record not found for key: {"GDPICTURE"}");
});
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();
});
#endregion PDF Burner
services.AddHttpClientService<GtxMessagingParams>(config.GetSection(nameof(GtxMessagingParams)));
services.TryAddSingleton<ISmsSender, GTXSmsSender>();
@@ -57,8 +85,23 @@ public static class DependencyInjection
services.AddMediatR(cfg =>
{
cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly());
cfg.AddBehavior<CreateHistoryBehavior>();
cfg.AddBehavior<SavePdfBehavior>();
#if WINDOWS
cfg.AddBehavior<SendEmailBehavior>();
cfg.AddBehavior<WritePdfBehavior>();
cfg.AddBehavior<PdfMergeBehavior>();
cfg.AddBehavior<AddReportBehavior>();
#endif
});
// Add memory cache
services.AddMemoryCache();
// Register mail services
services.AddScoped<IEnvelopeMailService, EnvelopeMailService>();
return services;
}
}

View File

@@ -1,5 +1,5 @@
using AutoMapper;
using EnvelopeGenerator.Application.Interfaces.Repositories;
using EnvelopeGenerator.Application.Common.Interfaces.Repositories;
using EnvelopeGenerator.Domain.Constants;
using MediatR;

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net7.0;net8.0;net9.0</TargetFrameworks>
<TargetFrameworks>net7.0;net8.0;net9.0;net8.0-windows</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
@@ -14,7 +14,8 @@
<ItemGroup>
<PackageReference Include="Dapper" Version="2.1.66" />
<PackageReference Include="DigitalData.Core.Abstraction.Application" Version="1.2.1" />
<PackageReference Include="DevExpress.Reporting.Core" Version="21.2.4" />
<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 +26,36 @@
<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" />
<PackageReference Include="GdPicture" Version="14.3.19.1" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0' Or '$(TargetFramework)' == 'net8.0-windows'">
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
<PackageReference Include="System.Formats.Asn1" Version="9.0.10" />
<PackageReference Include="GdPicture" Version="14.3.19.1" />
<PackageReference Include="GdPicture.runtimes.windows" Version="14.3.19.1" />
<PackageReference Include="GdPicture.runtimes.linux" Version="14.3.19.1" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
<PackageReference Include="System.Formats.Asn1" Version="9.0.10" />
<PackageReference Include="GdPicture" Version="14.3.19.1" />
<PackageReference Include="GdPicture.runtimes.windows" Version="14.3.19.1" />
<PackageReference Include="GdPicture.runtimes.linux" Version="14.3.19.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EnvelopeGenerator.CommonServices\EnvelopeGenerator.CommonServices.vbproj" />
<ProjectReference Include="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj" />
<ProjectReference Include="..\EnvelopeGenerator.PdfEditor\EnvelopeGenerator.PdfEditor.csproj" />
</ItemGroup>
<ItemGroup>
@@ -79,7 +93,7 @@
</PackageReference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0' Or '$(TargetFramework)' == 'net8.0-windows'">
<PackageReference Include="AutoMapper" Version="14.0.0" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
<PackageReference Include="CommandDotNet">

View File

@@ -1,8 +1,8 @@
using AutoMapper;
using EnvelopeGenerator.Application.Interfaces.SQLExecutor;
using EnvelopeGenerator.Domain.Entities;
using MediatR;
using EnvelopeGenerator.Application.Common.Dto.Receiver;
using EnvelopeGenerator.Application.Common.Interfaces.SQLExecutor;
namespace EnvelopeGenerator.Application.EnvelopeReceivers.Commands;

View File

@@ -91,6 +91,8 @@ public class ReadEnvelopeReceiverQueryHandler : IRequestHandler<ReadEnvelopeRece
{
private readonly IRepository<EnvelopeReceiver> _repo;
private readonly IRepository<Receiver> _rcvRepo;
private readonly IMapper _mapper;
/// <summary>
@@ -98,10 +100,11 @@ public class ReadEnvelopeReceiverQueryHandler : IRequestHandler<ReadEnvelopeRece
/// </summary>
/// <param name="envelopeReceiver"></param>
/// <param name="mapper"></param>
public ReadEnvelopeReceiverQueryHandler(IRepository<EnvelopeReceiver> envelopeReceiver, IMapper mapper)
public ReadEnvelopeReceiverQueryHandler(IRepository<EnvelopeReceiver> envelopeReceiver, IRepository<Receiver> rcvRepo, IMapper mapper)
{
_repo = envelopeReceiver;
_mapper = mapper;
_rcvRepo = rcvRepo;
}
/// <summary>
@@ -138,6 +141,14 @@ public class ReadEnvelopeReceiverQueryHandler : IRequestHandler<ReadEnvelopeRece
.Include(er => er.Receiver)
.ToListAsync(cancel);
if (request.Receiver.HasAnyCriteria && envRcvs.Any())
{
var receiver = await _rcvRepo.ReadOnly().Where(request.Receiver).FirstAsync(cancel);
foreach (var envRcv in envRcvs)
envRcv.Envelope?.Documents?.First().Elements.RemoveAll(s => s.ReceiverId != receiver.Id);
}
return _mapper.Map<List<EnvelopeReceiverDto>>(envRcvs);
}
}

View File

@@ -0,0 +1,92 @@
using AutoMapper;
using DigitalData.Core.Abstraction.Application.Repository;
using DigitalData.Core.Exceptions;
using EnvelopeGenerator.Domain.Entities;
using MediatR;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace EnvelopeGenerator.Application.EnvelopeReports;
/// <summary>
///
/// </summary>
public record ReadEnvelopeReportQuery(int EnvelopeId) : IRequest<IEnumerable<EnvelopeReport>>
{
/// <summary>
///
/// </summary>
[JsonIgnore]
[NotMapped]
public bool ThrowIfNotFound { get; init; } = true;
};
/// <summary>
///
/// </summary>
public static class ReadEnvelopeReportQueryExtensions
{
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="envelopeId"></param>
/// <param name="throwIfNotFound"></param>
/// <param name="cancel"></param>
/// <returns></returns>
public static Task<IEnumerable<EnvelopeReport>> ReadEnvelopeReportAsync(this ISender sender, int envelopeId, bool throwIfNotFound = true, CancellationToken cancel = default)
=> sender.Send(new ReadEnvelopeReportQuery(envelopeId)
{
ThrowIfNotFound = throwIfNotFound
}, cancel);
}
/// <summary>
///
/// </summary>
public class ReadEnvelopeReportQueryHandler : IRequestHandler<ReadEnvelopeReportQuery, IEnumerable<EnvelopeReport>>
{
/// <summary>
///
/// </summary>
private readonly IRepository<EnvelopeReport> _repo;
/// <summary>
///
/// </summary>
private readonly IMapper _mapper;
/// <summary>
///
/// </summary>
/// <param name="repo"></param>
/// <param name="mapper"></param>
public ReadEnvelopeReportQueryHandler(IRepository<EnvelopeReport> repo, IMapper mapper)
{
_repo = repo;
_mapper = mapper;
}
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="cancel"></param>
/// <returns></returns>
public async Task<IEnumerable<EnvelopeReport>> Handle(ReadEnvelopeReportQuery request, CancellationToken cancel = default)
{
var reports = await _repo.Where(r => r.EnvelopeId == request.EnvelopeId).ToListAsync(cancel);
var reportDtos = _mapper.Map<IEnumerable<EnvelopeReport>>(reports);
if(request.ThrowIfNotFound && !reportDtos.Any())
throw new NotFoundException($"EnvelopeReport with EnvelopeId '{request.EnvelopeId}' was not found.");
return reportDtos;
}
}

View File

@@ -1,6 +1,6 @@
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Application.Common.Dto;
using EnvelopeGenerator.Application.Interfaces.SQLExecutor;
using EnvelopeGenerator.Application.Common.Interfaces.SQLExecutor;
using MediatR;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

View File

@@ -1,10 +1,10 @@
using AutoMapper;
using EnvelopeGenerator.Application.Interfaces.SQLExecutor;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Application.Common.Dto;
using EnvelopeGenerator.Application.Common.Interfaces.SQLExecutor;
namespace EnvelopeGenerator.Application.Envelopes.Commands;

View File

@@ -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);
}
}

View File

@@ -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) { }
}

View File

@@ -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) { }
}

View File

@@ -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) { }
}

View File

@@ -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) { }
}

View File

@@ -34,7 +34,7 @@ public record CreateHistoryCommand : EnvelopeReceiverQueryBase, IRequest<History
/// <summary>
///
/// </summary>
public DateTime AddedWhen { get; } = DateTime.Now;
public DateTime AddedWhen { get; } = DateTime.UtcNow;
/// <summary>
///

View File

@@ -0,0 +1,99 @@
#if WINDOWS
using MediatR;
using EnvelopeGenerator.Application.EnvelopeReports;
using EnvelopeGenerator.Application.Exceptions;
using EnvelopeGenerator.Domain.Entities;
using Microsoft.Extensions.Logging;
using EnvelopeGenerator.CommonServices;
namespace EnvelopeGenerator.Application.Pdf.Behaviors;
/// <summary>
///
/// </summary>
public class AddReportBehavior : IPipelineBehavior<BurnPdfCommand, byte[]>
{
private readonly ISender _sender;
private readonly ILogger<AddReportBehavior> _logger;
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="logger"></param>
public AddReportBehavior(ISender sender, ILogger<AddReportBehavior> logger)
{
_sender = sender;
_logger = logger;
}
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="next"></param>
/// <param name="cancel"></param>
/// <returns></returns>
public async Task<byte[]> Handle(BurnPdfCommand request, RequestHandlerDelegate<byte[]> next, CancellationToken cancel)
{
var docResult = await next(cancel);
request.Report = await CreateReport(request.Envelope!, cancel);
return docResult;
}
/// <summary>
///
/// </summary>
/// <param name="envelope"></param>
/// <param name="cancel"></param>
/// <returns></returns>
/// <exception cref="CreateReportException"></exception>
public async Task<byte[]> CreateReport(Envelope envelope, CancellationToken cancel)
{
var oItems = await _sender.ReadEnvelopeReportAsync(envelope.Id, cancel: cancel);
if (!oItems.Any())
{
throw new CreateReportException("No report data found!");
}
var oBuffer = DoCreateReport(oItems);
return oBuffer;
}
private static byte[] DoCreateReport(IEnumerable<EnvelopeReport> oItems)
{
var oSource = new ReportSource { Items = oItems };
var oReport = new rptEnvelopeHistory
{
DataSource = oSource,
DataMember = "Items"
};
// Creating report in memory
oReport.CreateDocument();
// Exporting report to stream
using var oStream = new MemoryStream();
oReport.ExportToPdf(oStream);
// Writing report to buffer
return oStream.ToArray();
}
/// <summary>
///
/// </summary>
public class ReportSource
{
/// <summary>
///
/// </summary>
public required IEnumerable<EnvelopeReport> Items { get; init; }
}
}
#endif

View File

@@ -0,0 +1,49 @@
using MediatR;
using EnvelopeGenerator.Application.Histories.Commands;
using EnvelopeGenerator.Domain.Constants;
using Microsoft.Extensions.Logging;
namespace EnvelopeGenerator.Application.Pdf.Behaviors;
/// <summary>
///
/// </summary>
public class CreateHistoryBehavior : IPipelineBehavior<BurnPdfCommand, byte[]>
{
private readonly ISender _sender;
private readonly ILogger<CreateHistoryBehavior> _logger;
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="logger"></param>
public CreateHistoryBehavior(ISender sender, ILogger<CreateHistoryBehavior> logger)
{
_sender = sender;
_logger = logger;
}
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="next"></param>
/// <param name="cancel"></param>
/// <returns></returns>
public async Task<byte[]> Handle(BurnPdfCommand request, RequestHandlerDelegate<byte[]> next, CancellationToken cancel)
{
var doc = await next(cancel);
if (!request.Debug)
await _sender.Send(new CreateHistoryCommand()
{
EnvelopeId = request.EnvelopeId,
UserReference = "System",
Status = EnvelopeStatus.EnvelopeReportCreated,
}, cancel);
return doc;
}
}

View File

@@ -0,0 +1,71 @@
#if WINDOWS
using EnvelopeGenerator.Application.Common.Extensions;
using EnvelopeGenerator.Application.Exceptions;
using EnvelopeGenerator.Domain.Constants;
using GdPicture14;
using MediatR;
namespace EnvelopeGenerator.Application.Pdf.Behaviors;
/// <summary>
///
/// </summary>
public class PdfMergeBehavior : IPipelineBehavior<BurnPdfCommand, byte[]>
{
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="next"></param>
/// <param name="cancel"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<byte[]> Handle(BurnPdfCommand request, RequestHandlerDelegate<byte[]> next, CancellationToken cancel)
{
var doc = await next(cancel);
if (request.Report is null)
throw new InvalidOperationException("The final document report could not be merged."
+ "There may be an error related to the behavior register order."
+ "Request details:\n" + request.ToJson(Format.Json.ForDiagnostics));
using var oDocumentStream = new MemoryStream(doc);
using var oReportStream = new MemoryStream(request.Report);
using var oFinalStream = new MemoryStream();
using var oDocumentPDF = new GdPicturePDF();
using var oReportPDF = new GdPicturePDF();
GdPictureStatus oStatus = GdPictureStatus.OK;
// Load the source file into memory
oDocumentPDF.LoadFromStream(oDocumentStream, true);
oStatus = oDocumentPDF.GetStat();
if (oStatus != GdPictureStatus.OK)
throw new MergeDocumentException($"Document could not be loaded: {oStatus}."
+ "Request details:\n" + request.ToJson(Format.Json.ForDiagnostics));
// Load the report file into memory
oReportPDF.LoadFromStream(oReportStream, true);
oStatus = oReportPDF.GetStat();
if (oStatus != GdPictureStatus.OK)
throw new MergeDocumentException($"Report could not be loaded: {oStatus}."
+ "Request details:\n" + request.ToJson(Format.Json.ForDiagnostics));
// Merge the documents
var oMergedPDF = oDocumentPDF.Merge2Documents(oDocumentPDF, oReportPDF);
oStatus = oMergedPDF.GetStat();
if (oStatus != GdPictureStatus.OK)
throw new MergeDocumentException($"Documents could not be merged: {oStatus}."
+ "Request details:\n" + request.ToJson(Format.Json.ForDiagnostics));
// Convert to byte
oMergedPDF.SaveToStream(oFinalStream);
oStatus = oDocumentPDF.GetStat();
if (oStatus != GdPictureStatus.OK)
throw new MergeDocumentException($"Document could not be converted to byte: {oStatus}."
+ "Request details:\n" + request.ToJson(Format.Json.ForDiagnostics));
return oFinalStream.ToArray();
}
}
#endif

View File

@@ -0,0 +1,23 @@
using MediatR;
namespace EnvelopeGenerator.Application.Pdf.Behaviors;
/// <summary>
///
/// </summary>
public class SavePdfBehavior : IPipelineBehavior<BurnPdfCommand, byte[]>
{
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="next"></param>
/// <param name="cancel"></param>
/// <returns></returns>
public async Task<byte[]> Handle(BurnPdfCommand request, RequestHandlerDelegate<byte[]> next, CancellationToken cancel)
{
var docResult = await next(cancel);
var base64 = Convert.ToBase64String(docResult);
return docResult;
}
}

View File

@@ -0,0 +1,113 @@
using EnvelopeGenerator.Application.Histories.Commands;
using EnvelopeGenerator.Domain.Constants;
using MediatR;
using Microsoft.Extensions.Logging;
namespace EnvelopeGenerator.Application.Pdf.Behaviors;
/// <summary>
///
/// </summary>
public class SendEmailBehavior : IPipelineBehavior<BurnPdfCommand, byte[]>
{
private readonly ILogger<SendEmailBehavior> _logger;
private readonly ISender _sender;
/// <summary>
///
/// </summary>
/// <param name="logger"></param>
/// <param name="sender"></param>
public SendEmailBehavior(ILogger<SendEmailBehavior> logger, ISender sender)
{
_logger = logger;
_sender = sender;
}
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="next"></param>
/// <param name="cancel"></param>
/// <returns></returns>
public async Task<byte[]> Handle(BurnPdfCommand request, RequestHandlerDelegate<byte[]> next, CancellationToken cancel)
{
var docResult = await next(cancel);
var mailToCreator = request.Envelope!.FinalEmailToCreator;
var mailToReceivers = request.Envelope.FinalEmailToReceivers;
if (mailToCreator is not null && mailToCreator != (int)FinalEmailType.No)
{
_logger.LogDebug("Sending email to creator ...");
await SendFinalEmailToCreatorAsync(request, cancel); // , pAttachment
}
else
{
_logger.LogWarning("No SendFinalEmailToCreatorAsync - mailToCreator [{mailToCreator}] <> [{FinalEmailType.No}] ",
mailToCreator, FinalEmailType.No);
}
if (mailToReceivers != (int)FinalEmailType.No)
{
_logger.LogDebug("Sending emails to receivers...");
await SendFinalEmailToReceiversAsync(request, cancel); // , pAttachment
}
else
{
_logger.LogWarning("No SendFinalEmailToReceiversAsync - mailToReceivers [{mailToReceivers}] <> [{FinalEmailType.No}] ",
mailToReceivers, FinalEmailType.No);
}
return docResult;
}
private async Task SendFinalEmailToCreatorAsync(BurnPdfCommand request, CancellationToken cancel) //, string pAttachment
{
bool oIncludeAttachment = SendFinalEmailWithAttachment((int)request.Envelope!.FinalEmailToCreator!);
// string oAttachment = string.Empty;
_logger.LogDebug("Attachment included: [{oIncludeAttachment}]", oIncludeAttachment);
if (oIncludeAttachment)
{
// oAttachment = pAttachment;
}
await _sender.Send(new CreateHistoryCommand()
{
EnvelopeId = request.Envelope!.Id,
Status = EnvelopeStatus.MessageCompletionSent,
UserReference = request.Envelope.User.Email,
}, cancel);
}
private async Task SendFinalEmailToReceiversAsync(BurnPdfCommand request, CancellationToken cancel) //, string pAttachment
{
bool oIncludeAttachment = SendFinalEmailWithAttachment((int)request.Envelope!.FinalEmailToReceivers!);
// string oAttachment = string.Empty;
_logger.LogDebug("Attachment included: [{oIncludeAttachment}]", oIncludeAttachment);
if (oIncludeAttachment)
{
// oAttachment = pAttachment;
}
// TODO update CreateHistoryCommand to be able to create all records together
foreach (var receiver in request.Envelope.EnvelopeReceivers!)
{
if (receiver.Receiver?.EmailAddress != null)
{
await _sender.Send(new CreateHistoryCommand()
{
EnvelopeId = request.Envelope.Id,
Status = EnvelopeStatus.MessageCompletionSent,
UserReference = receiver.Receiver.EmailAddress,
}, cancel);
}
}
}
private static bool SendFinalEmailWithAttachment(int type) => type == (int)FinalEmailType.YesWithAttachment;
}

View File

@@ -0,0 +1,64 @@
#if WINDOWS
using EnvelopeGenerator.Application.Configs;
using MediatR;
using Microsoft.Extensions.Logging;
namespace EnvelopeGenerator.Application.Pdf.Behaviors;
/// <summary>
///
/// </summary>
public class WritePdfBehavior : IPipelineBehavior<BurnPdfCommand, byte[]>
{
private readonly ISender _sender;
private readonly ILogger<WritePdfBehavior> _logger;
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="logger"></param>
public WritePdfBehavior(ISender sender, ILogger<WritePdfBehavior> logger)
{
_sender = sender;
_logger = logger;
}
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="next"></param>
/// <param name="cancel"></param>
/// <returns></returns>
public async Task<byte[]> Handle(BurnPdfCommand request, RequestHandlerDelegate<byte[]> next, CancellationToken cancel)
{
var docResult = await next(cancel);
var config = await _sender.ReadDefaultConfigAsync(cancel);
var exportPath = config.ExportPath ?? throw new InvalidOperationException(nameof(WritePdfBehavior) + " is not possible."
+ "No export path found in config table.");
var dirPath = Path.Combine(exportPath, request.Envelope!.Uuid);
_logger.LogDebug("dirPath is {dirPath}", dirPath);
if (!Directory.Exists(dirPath))
{
_logger.LogDebug("Directory not existing. Creating ...");
Directory.CreateDirectory(dirPath);
}
var outputFilePath = Path.Combine(dirPath, $"{request.Envelope.Uuid}.pdf");
_logger.LogDebug("Writing finalized Pdf to disk..");
_logger.LogInformation("Output path is {outputFilePath}", outputFilePath);
await File.WriteAllBytesAsync(outputFilePath, docResult, cancel);
return docResult;
}
}
#endif

View File

@@ -0,0 +1,305 @@
using DigitalData.Core.Abstraction.Application.Repository;
using DigitalData.Core.Exceptions;
using EnvelopeGenerator.Application.Common.Configurations;
using EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
using EnvelopeGenerator.Application.Common.Extensions;
using EnvelopeGenerator.Application.Exceptions;
using EnvelopeGenerator.Domain.Constants;
using EnvelopeGenerator.Domain.Entities;
using GdPicture14;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
namespace EnvelopeGenerator.Application.Pdf;
/// <summary>
///
/// </summary>
public record BurnPdfCommand(int? EnvelopeId = null, string? EnvelopeUuid = null) : IRequest<byte[]>
{
internal bool Debug { get; set; }
internal Envelope? Envelope { get; set; }
#if WINDOWS
internal byte[]? Report { get; set; }
#endif
}
/// <summary>
///
/// </summary>
public static class BurnPdfCommandExtensions
{
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="envelopeId"></param>
/// <param name="cancel"></param>
/// <returns></returns>
public static Task<byte[]> BurnPdf(this ISender sender, int envelopeId, CancellationToken cancel = default)
=> sender.Send(new BurnPdfCommand(EnvelopeId: envelopeId), cancel);
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="envelopeUuid"></param>
/// <param name="cancel"></param>
/// <returns></returns>
public static Task<byte[]> BurnPdf(this ISender sender, string envelopeUuid, CancellationToken cancel = default)
=> sender.Send(new BurnPdfCommand(EnvelopeUuid: envelopeUuid), cancel);
}
/// <summary>
///
/// </summary>
public class BurnPdfCommandHandler : IRequestHandler<BurnPdfCommand, byte[]>
{
private readonly PDFBurnerParams _options;
private readonly AnnotationManager _manager;
private readonly ILogger<BurnPdfCommandHandler> _logger;
private readonly IRepository<Envelope> _envRepo;
private readonly IRepository<Domain.Entities.DocumentStatus> _docStatusRepo;
private readonly IConfiguration _config;
/// <summary>
///
/// </summary>
/// <param name="pdfBurnerParams"></param>
/// <param name="manager"></param>
/// <param name="logger"></param>
/// <param name="envRepo"></param>
/// <param name="docStatusRepo"></param>
/// <param name="config"></param>
public BurnPdfCommandHandler(IOptions<PDFBurnerParams> pdfBurnerParams, AnnotationManager manager, ILogger<BurnPdfCommandHandler> logger, IRepository<Envelope> envRepo, IRepository<Domain.Entities.DocumentStatus> docStatusRepo, IConfiguration config)
{
_options = pdfBurnerParams.Value;
_manager = manager;
_docStatusRepo = docStatusRepo;
_logger = logger;
_envRepo = envRepo;
_config = config;
}
/// <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)
{
request.Debug = _config.GetValue<bool>("Debug");
var envQuery =
request.EnvelopeId is not null ? _envRepo.Where(env => env.Id == request.EnvelopeId) :
request.EnvelopeUuid is not null ? _envRepo.Where(env => env.Uuid == request.EnvelopeUuid) :
throw new BadRequestException("Request validation failed: Either Envelope Id or Envelope Uuid must be provided.");
request.Envelope = await envQuery
.Include(env => env.Documents!).ThenInclude(doc => doc.Elements!).ThenInclude(element => element.Annotations)
.Include(env => env.User)
.Include(env => env.EnvelopeReceivers!).ThenInclude(envRcv => envRcv.Receiver)
.FirstOrDefaultAsync(cancel)
?? throw new BadRequestException($"Envelope could not be found. Request details:\n" +
request.ToJson(Format.Json.ForDiagnostics));
var doc = request.Envelope.Documents?.FirstOrDefault()
?? throw new NotFoundException($"Document could not be located within the specified envelope. Request details:\n" +
request.ToJson(Format.Json.ForDiagnostics));
if (doc.ByteData is null)
throw new InvalidOperationException($"Document byte data is missing, indicating a potential data integrity issue. Request details:\n" +
request.ToJson(Format.Json.ForDiagnostics));
return doc.Elements?.SelectMany(e => e.Annotations ?? Enumerable.Empty<ElementAnnotation>()).Where(annot => annot is not null).Any() ?? false
? BurnElementAnnotsToPDF(doc.ByteData, doc.Elements)
: BurnInstantJSONAnnotsToPDF(doc.ByteData, await _docStatusRepo
.Where(status => status.EnvelopeId == request.Envelope.Id)
.Select(status => status.Value)
.ToListAsync(cancel));
}
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;
}
}
}
}

View File

@@ -1,5 +1,5 @@
using EnvelopeGenerator.Application.Common.Configurations;
using EnvelopeGenerator.Application.Interfaces.Services;
using EnvelopeGenerator.Application.Common.Interfaces.Services;
using Microsoft.Extensions.Options;
using OtpNet;
using QRCoder;

View File

@@ -1,12 +1,12 @@
using AutoMapper;
using DigitalData.Core.Application;
using DigitalData.Core.Abstraction.Application.DTO;
using EnvelopeGenerator.Application.Interfaces.Services;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Application.Interfaces.Repositories;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using EnvelopeGenerator.Application.Common.Dto;
using EnvelopeGenerator.Application.Common.Interfaces.Repositories;
using EnvelopeGenerator.Application.Common.Interfaces.Services;
namespace EnvelopeGenerator.Application.Services;

View File

@@ -1,9 +1,9 @@
using AutoMapper;
using DigitalData.Core.Application;
using EnvelopeGenerator.Application.Interfaces.Services;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Application.Interfaces.Repositories;
using EnvelopeGenerator.Application.Common.Dto;
using EnvelopeGenerator.Application.Common.Interfaces.Repositories;
using EnvelopeGenerator.Application.Common.Interfaces.Services;
namespace EnvelopeGenerator.Application.Services;

View File

@@ -1,9 +1,9 @@
using AutoMapper;
using DigitalData.Core.Application;
using EnvelopeGenerator.Application.Interfaces.Services;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Application.Interfaces.Repositories;
using EnvelopeGenerator.Application.Common.Dto;
using EnvelopeGenerator.Application.Common.Interfaces.Repositories;
using EnvelopeGenerator.Application.Common.Interfaces.Services;
namespace EnvelopeGenerator.Application.Services;

View File

@@ -1,12 +1,12 @@
using AutoMapper;
using DigitalData.Core.Application;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Application.Interfaces.Repositories;
using DigitalData.Core.Abstraction.Application.DTO;
using Microsoft.Extensions.Logging;
using EnvelopeGenerator.Application.Interfaces.Services;
using EnvelopeGenerator.Domain.Constants;
using EnvelopeGenerator.Application.Common.Dto;
using EnvelopeGenerator.Application.Common.Interfaces.Repositories;
using EnvelopeGenerator.Application.Common.Interfaces.Services;
namespace EnvelopeGenerator.Application.Services;

View File

@@ -1,9 +1,9 @@
using AutoMapper;
using DigitalData.Core.Application;
using EnvelopeGenerator.Application.Interfaces.Services;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Application.Interfaces.Repositories;
using EnvelopeGenerator.Application.Common.Dto;
using EnvelopeGenerator.Application.Common.Interfaces.Repositories;
using EnvelopeGenerator.Application.Common.Interfaces.Services;
namespace EnvelopeGenerator.Application.Services;

View File

@@ -1,12 +1,12 @@
using AutoMapper;
using DigitalData.Core.Application;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Application.Interfaces.Repositories;
using EnvelopeGenerator.Application.Interfaces.Services;
using DigitalData.Core.Abstraction.Application.DTO;
using EnvelopeGenerator.Domain.Constants;
using EnvelopeGenerator.Application.Common.Dto.History;
using EnvelopeGenerator.Application.Common.Dto.Receiver;
using EnvelopeGenerator.Application.Common.Interfaces.Repositories;
using EnvelopeGenerator.Application.Common.Interfaces.Services;
namespace EnvelopeGenerator.Application.Services;

View File

@@ -5,13 +5,13 @@ using DigitalData.EmailProfilerDispatcher.Abstraction.Services;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using EnvelopeGenerator.Application.Interfaces.Services;
using DigitalData.Core.Abstraction.Application.DTO;
using EnvelopeGenerator.Domain.Constants;
using EnvelopeGenerator.Application.Common.Configurations;
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiverReadOnly;
using EnvelopeGenerator.Application.Common.Extensions;
using EnvelopeGenerator.Application.Common.Interfaces.Services;
namespace EnvelopeGenerator.Application.Services;

Some files were not shown because too many files have changed in this diff Show More