Compare commits
136 Commits
140d271b28
...
feat/final
| Author | SHA1 | Date | |
|---|---|---|---|
| b996102a86 | |||
| 4b1d316b46 | |||
| 51234cda2a | |||
| e719dded48 | |||
| 6195d99fab | |||
| 50a372a224 | |||
| 35dd2e8e07 | |||
| fac5419589 | |||
| d442ad0ce0 | |||
| cbe2acc37d | |||
| 40cc467b47 | |||
| d1513dab5e | |||
| dee424e7db | |||
| e57e9e1834 | |||
| 5b30465126 | |||
| 2dfa1de7e1 | |||
| e68965543e | |||
| 958bcdfc42 | |||
| d88ed324be | |||
| 380b141738 | |||
| f3a15216a8 | |||
| 8a48bf6b51 | |||
| 0038eeed76 | |||
| 4ed118ed2b | |||
|
|
350aa259c8 | ||
|
|
737de2202e | ||
|
|
ff60cd7ef8 | ||
|
|
e1aa7fe650 | ||
|
|
9c0b1e3fa8 | ||
| 6b34b55c4f | |||
| 4a5608249e | |||
|
|
965838513f | ||
|
|
9c4766518e | ||
|
|
292b6b2ccf | ||
|
|
6f9b5d4b13 | ||
|
|
8459706c45 | ||
|
|
972c63388e | ||
|
|
cde9ed06a1 | ||
|
|
d94f885e92 | ||
|
|
028785a8c9 | ||
|
|
e6285f13f7 | ||
| 35b7b1a080 | |||
| 67d0980c63 | |||
| c6a99b56a2 | |||
| 31f5d1f340 | |||
| a2df5d7691 | |||
| f8c586dd31 | |||
| 8aea3c8301 | |||
| 495adb8c31 | |||
| 86c0a65540 | |||
| d2e8f1fc5e | |||
| f8369e350f | |||
| b8a2ad97ef | |||
| ffffc2d470 | |||
| 36b03da084 | |||
| defa53fa26 | |||
| 6134b58a4c | |||
| 5299016b43 | |||
| 55c20e83d8 | |||
| f1a140faa7 | |||
| b20d25e5b9 | |||
| e21eb2c0d6 | |||
| d237b4ab95 | |||
| dff99b163d | |||
| 70fbf31b14 | |||
| 339e0e81cd | |||
| a386ad72bb | |||
| 02c5f286ec | |||
| 5fa358ca79 | |||
| 7233d2ce98 | |||
| 5784cc7a97 | |||
| f31f680f91 | |||
| e7c2d46ef0 | |||
| 85d70c1db4 | |||
| fb340fb08a | |||
| 7d3959ae51 | |||
| 9d4890b10d | |||
| b64f4d71f5 | |||
| b7d146ddb5 | |||
| 6a5c9a3489 | |||
|
|
15f6ee7be0 | ||
|
|
1051c5356f | ||
|
|
7b13350fbf | ||
|
|
2bada327d8 | ||
|
|
a47729ebca | ||
|
|
fcfed963b7 | ||
|
|
b2ace61cd4 | ||
|
|
77cdc83a4e | ||
|
|
a611df4914 | ||
|
|
1341f69ab1 | ||
|
|
0480513288 | ||
|
|
9dbd1b16b5 | ||
|
|
c649c93921 | ||
|
|
1843119b1b | ||
|
|
bc4371cb99 | ||
|
|
05130d6163 | ||
| 567b9c9565 | |||
| b798181f91 | |||
| 7e8fc25ec9 | |||
| db76162697 | |||
| 2b4573ea73 | |||
| 4a043ed247 | |||
| a62a035ec6 | |||
| 1713a65014 | |||
| 695d7c83e0 | |||
| 428f71863d | |||
| cce2f8f90e | |||
|
|
86c9fdfcd7 | ||
|
|
89ec887510 | ||
|
|
7d5b988842 | ||
|
|
3c456562cc | ||
|
|
4d6b01030c | ||
|
|
75e7e9925b | ||
|
|
0a175b9e9d | ||
|
|
f611e74de1 | ||
|
|
08ca116628 | ||
|
|
4997f7d75c | ||
| b5cd42b6fa | |||
| 187f4a42fc | |||
| 23d4b2f31e | |||
| 8e71e5b4bb | |||
| b693615561 | |||
| 36dc9266bc | |||
| 9aabe270b4 | |||
| b303b7be06 | |||
| 02937360ea | |||
| c2735b92e0 | |||
| 568f43186c | |||
| 3bc5439b5a | |||
| 22b494a262 | |||
| 209785dda5 | |||
| 44ea893f05 | |||
| b4aa7984aa | |||
| 7c5a505ad1 | |||
| bd6d57e1e8 | |||
| 8403ce2c6a |
@@ -0,0 +1,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>
|
||||
730
EnvelopeGenerator.Application.VB/Reports/rptEnvelopeHistory.Designer.vb
generated
Normal file
730
EnvelopeGenerator.Application.VB/Reports/rptEnvelopeHistory.Designer.vb
generated
Normal 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
|
||||
129
EnvelopeGenerator.Application.VB/Reports/rptEnvelopeHistory.resx
Normal file
129
EnvelopeGenerator.Application.VB/Reports/rptEnvelopeHistory.resx
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
|
||||
Public Class rptEnvelopeHistory
|
||||
|
||||
End Class
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Configurations;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class GdPictureParams
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string License { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,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;
|
||||
}
|
||||
@@ -82,7 +82,7 @@ public record EnvelopeDto
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool UseAccessCode { get; set; } = true;
|
||||
public bool? UseAccessCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
|
||||
@@ -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!;
|
||||
}
|
||||
@@ -36,6 +36,8 @@ public class MappingProfile : Profile
|
||||
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>();
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
using EnvelopeGenerator.Application.Exceptions;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class Annotation
|
||||
{
|
||||
private string? _id;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int EnvelopeId { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int ReceiverId { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int Index { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string EgName { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool HasStructuredID { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool IsLabel
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(EgName))
|
||||
return false;
|
||||
|
||||
var parts = EgName.Split('_');
|
||||
return parts.Length > 1 && parts[1] == "label";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? Id
|
||||
{
|
||||
get => _id;
|
||||
set
|
||||
{
|
||||
_id = value;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
throw new BurnAnnotationException("The identifier of annotation is null or empty.");
|
||||
|
||||
var parts = value.Split('#');
|
||||
|
||||
if (parts.Length != 4)
|
||||
return;
|
||||
// throw new BurnAnnotationException($"The identifier of annotation has more or less than 4 sub-part. Id: {_id}");
|
||||
|
||||
if (!int.TryParse(parts[0], out int envelopeId))
|
||||
throw new BurnAnnotationException($"The envelope ID of annotation is not integer. Id: {_id}");
|
||||
EnvelopeId = envelopeId;
|
||||
|
||||
if (!int.TryParse(parts[1], out int receiverId))
|
||||
throw new BurnAnnotationException($"The receiver ID of annotation is not integer. Id: {_id}");
|
||||
ReceiverId = receiverId;
|
||||
|
||||
if (!int.TryParse(parts[2], out int index))
|
||||
throw new BurnAnnotationException($"The index of annotation is not integer. Id: {_id}");
|
||||
Index = index;
|
||||
|
||||
EgName = parts[3];
|
||||
HasStructuredID = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<double>? Bbox { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool IsSignature { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? ImageAttachmentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Lines? Lines { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int PageIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? StrokeColor { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="Binary"></param>
|
||||
/// <param name="ContentType"></param>
|
||||
public record Attachment(string Binary, string ContentType);
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="Name"></param>
|
||||
/// <param name="Value"></param>
|
||||
public record FormFieldValue(string Name, string? Value = null);
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="Lines"></param>
|
||||
/// <param name="StrokeColor"></param>
|
||||
public record Ink(Lines Lines, string? StrokeColor = null);
|
||||
@@ -0,0 +1,50 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class InstantData
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<Annotation>? Annotations { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IEnumerable<List<Annotation>>? AnnotationsByReceiver
|
||||
{
|
||||
get
|
||||
{
|
||||
return Annotations?
|
||||
.Where(a => a.HasStructuredID)
|
||||
.GroupBy(a => a.ReceiverId)
|
||||
.Select(g => g.ToList());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IEnumerable<List<Annotation>>? UnstructuredAnnotations
|
||||
{
|
||||
get
|
||||
{
|
||||
return Annotations?
|
||||
.Where(a => !a.HasStructuredID)
|
||||
.GroupBy(a => a.ReceiverId)
|
||||
.Select(g => g.ToList());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Dictionary<string, Attachment>? Attachments { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<FormFieldValue>? FormFieldValues { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="Points"></param>
|
||||
public record Lines(List<List<List<float>>> Points);
|
||||
@@ -0,0 +1,57 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record ThirdPartyModuleDto
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool Active { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Name { get; init; } = default!;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? Description { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string License { get; init; } = default!;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Version { get; init; } = default!;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? AddedWho { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public DateTime? AddedWhen { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? ChangedWho { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public DateTime? ChangedWhen { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
using EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using GdPicture14;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using SixLabors.ImageSharp;
|
||||
using System.Drawing;
|
||||
using EnvelopeGenerator.Application.Common.Extensions;
|
||||
using EnvelopeGenerator.Application.Common.Interfaces.Model;
|
||||
using EnvelopeGenerator.Application.Common.Configurations;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Extensions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class GdPictureExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="page"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="textStyle"></param>
|
||||
public static void AddFormFieldValue(this AnnotationManager manager, double x, double y, double width, double height, int page, string value, ITextStyle textStyle)
|
||||
{
|
||||
manager.SelectPage(page);
|
||||
|
||||
// Add the text annotation
|
||||
var ant = manager.AddTextAnnot((float)x, (float)y, (float)width, (float)height, value);
|
||||
|
||||
// Set the font properties
|
||||
ant.FontName = textStyle.FontName;
|
||||
ant.FontSize = textStyle.FontSize;
|
||||
ant.FontStyle = textStyle.FontStyle;
|
||||
|
||||
manager.SaveAnnotationsToPage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="pAnnotation"></param>
|
||||
/// <param name="formFieldValue"></param>
|
||||
/// <param name="options"></param>
|
||||
public static void AddFormFieldValue(this AnnotationManager manager, Annotation pAnnotation, FormFieldValue formFieldValue, PDFBurnerParams options)
|
||||
{
|
||||
var ffIndex = options.GetAnnotationIndex(pAnnotation.EgName);
|
||||
|
||||
// Convert pixels to Inches
|
||||
var oBounds = pAnnotation.Bbox?.Select(points => points.ToInches()).ToList();
|
||||
|
||||
if (oBounds is null || oBounds.Count < 4)
|
||||
return;
|
||||
|
||||
double oX = oBounds[0];
|
||||
double oY = oBounds[1] + options.YOffset * ffIndex + options.TopMargin;
|
||||
double oWidth = oBounds[2];
|
||||
double oHeight = oBounds[3];
|
||||
|
||||
manager.SelectPage(pAnnotation.PageIndex + 1);
|
||||
|
||||
// Add the text annotation
|
||||
var ant = manager.AddTextAnnot((float)oX, (float)oY, (float)oWidth, (float)oHeight, formFieldValue.Value);
|
||||
|
||||
// Set the font properties
|
||||
ant.FontName = options.FontName;
|
||||
ant.FontSize = options.FontSize;
|
||||
ant.FontStyle = options.FontStyle;
|
||||
|
||||
manager.SaveAnnotationsToPage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="page"></param>
|
||||
/// <param name="base64"></param>
|
||||
public static void AddImageAnnotation(this AnnotationManager manager, double x, double y, double width, double height, int page, string base64)
|
||||
{
|
||||
manager.SelectPage(page);
|
||||
manager.AddEmbeddedImageAnnotFromBase64(base64, (float)x, (float)y, (float)width, (float)height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="pAnnotation"></param>
|
||||
/// <param name="pAttachments"></param>
|
||||
public static void AddImageAnnotation(this AnnotationManager manager, Annotation pAnnotation, Dictionary<string, Attachment> pAttachments)
|
||||
{
|
||||
var oAttachment = pAttachments
|
||||
.Where(a => a.Key == pAnnotation.ImageAttachmentId)
|
||||
.SingleOrDefault();
|
||||
|
||||
if (oAttachment.Value == null)
|
||||
return;
|
||||
|
||||
// Convert pixels to Inches
|
||||
var oBounds = pAnnotation.Bbox?.Select(post => post.ToInches()).ToList();
|
||||
|
||||
if (oBounds is null || oBounds.Count < 4)
|
||||
return;
|
||||
|
||||
var oX = oBounds[0];
|
||||
var oY = oBounds[1];
|
||||
var oWidth = oBounds[2];
|
||||
var oHeight = oBounds[3];
|
||||
|
||||
manager.SelectPage(pAnnotation.PageIndex + 1);
|
||||
manager.AddEmbeddedImageAnnotFromBase64(oAttachment.Value.Binary, (float)oX, (float)oY, (float)oWidth, (float)oHeight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="page"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void AddInkAnnotation(this AnnotationManager manager, int page, string value)
|
||||
{
|
||||
var ink = JsonConvert.DeserializeObject<Ink>(value);
|
||||
|
||||
var oSegments = ink?.Lines.Points;
|
||||
var oColor = ColorTranslator.FromHtml(ink?.StrokeColor ?? "#000000");
|
||||
manager.SelectPage(page);
|
||||
|
||||
if (oSegments is null)
|
||||
return;
|
||||
|
||||
foreach (var oSegment in oSegments)
|
||||
{
|
||||
var oPoints = oSegment
|
||||
.Select(points => points.ToPointF())
|
||||
.ToArray();
|
||||
|
||||
manager.AddFreeHandAnnot(oColor, oPoints);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="pAnnotation"></param>
|
||||
public static void AddInkAnnotation(this AnnotationManager manager, Annotation pAnnotation)
|
||||
{
|
||||
var oSegments = pAnnotation.Lines?.Points;
|
||||
var oColor = ColorTranslator.FromHtml(pAnnotation.StrokeColor ?? "#000000");
|
||||
manager.SelectPage(pAnnotation.PageIndex + 1);
|
||||
|
||||
if (oSegments is null)
|
||||
return;
|
||||
|
||||
foreach (var oSegment in oSegments)
|
||||
{
|
||||
var oPoints = oSegment
|
||||
.Select(points => points.ToPointF())
|
||||
.ToArray();
|
||||
|
||||
manager.AddFreeHandAnnot(oColor, oPoints);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System.Drawing;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Extensions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class MathematExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="points"></param>
|
||||
/// <returns></returns>
|
||||
public static PointF ToPointF(this List<float> points)
|
||||
{
|
||||
var pointsInch = points.Select(ToInches).ToList();
|
||||
return new PointF(pointsInch[0], pointsInch[1]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static double ToInches(this double value)
|
||||
{
|
||||
return value / 72.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static float ToInches(this float value)
|
||||
{
|
||||
return value / 72f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Drawing;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Interfaces.Model;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public interface ITextStyle
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string FontName { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int FontSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>")]
|
||||
public FontStyle FontStyle { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using MediatR;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Notifications.RemoveSignature.Handlers;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class RemoveDocResult : INotificationHandler<RemoveSignatureNotification>
|
||||
{
|
||||
private readonly IRepository<Envelope> _repo;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repository"></param>
|
||||
public RemoveDocResult(IRepository<Envelope> repository)
|
||||
{
|
||||
_repo = repository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="notification"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public Task Handle(RemoveSignatureNotification notification, CancellationToken cancel)
|
||||
{
|
||||
if(notification.EnvelopeId is null && notification.EnvelopeUuid is null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
return _repo.UpdateAsync(
|
||||
envelope => envelope.DocResult = null,
|
||||
query => {
|
||||
if (notification.EnvelopeId is int envelopeId)
|
||||
query = query.Where(envelope => envelope.Id == envelopeId);
|
||||
|
||||
if (notification.EnvelopeUuid is string uuid)
|
||||
query = query.Where(envelope => envelope.Uuid == uuid);
|
||||
|
||||
return query;
|
||||
}, cancel);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,16 @@
|
||||
using EnvelopeGenerator.Application.Common.Configurations;
|
||||
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
||||
using EnvelopeGenerator.Application.Services;
|
||||
using EnvelopeGenerator.Application.ThirdPartyModules.Queries;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using QRCoder;
|
||||
using System.Reflection;
|
||||
using GdPicture14;
|
||||
using EnvelopeGenerator.Application.Pdf.Behaviors;
|
||||
|
||||
namespace EnvelopeGenerator.Application;
|
||||
|
||||
@@ -47,6 +52,30 @@ public static class DependencyInjection
|
||||
services.Configure<AuthenticatorParams>(config.GetSection(nameof(AuthenticatorParams)));
|
||||
services.Configure<TotpSmsParams>(config.GetSection(nameof(TotpSmsParams)));
|
||||
|
||||
#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>();
|
||||
services.TryAddSingleton<IEnvelopeSmsHandler, EnvelopeSmsHandler>();
|
||||
@@ -56,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;
|
||||
}
|
||||
}
|
||||
@@ -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.4.0" />
|
||||
<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">
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,29 @@
|
||||
using MediatR;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using EnvelopeGenerator.Application.Common.Query;
|
||||
using EnvelopeGenerator.Application.Common.Dto;
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Application.Common.Extensions;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Envelopes.Queries;
|
||||
|
||||
/// <summary>
|
||||
/// Repräsentiert eine Abfrage für Umschläge.
|
||||
/// </summary>
|
||||
public record ReadEnvelopeQuery : EnvelopeQueryBase, IRequest
|
||||
public record ReadEnvelopeQuery : EnvelopeQueryBase, IRequest<IEnumerable<EnvelopeDto>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Abfrage des Include des Umschlags
|
||||
/// </summary>
|
||||
public EnvelopeStatusQuery? Status { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool? HasDocResult { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -65,4 +76,53 @@ public record EnvelopeStatusQuery
|
||||
/// Eine Liste von Statuswerten, die ignoriert werden werden.
|
||||
/// </summary>
|
||||
public EnvelopeStatus[]? Ignore { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadEnvelopeQueryHandler : IRequestHandler<ReadEnvelopeQuery, IEnumerable<EnvelopeDto>>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
private readonly IRepository<Envelope> _repo;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="mapper"></param>
|
||||
/// <param name="repo"></param>
|
||||
public ReadEnvelopeQueryHandler(IMapper mapper, IRepository<Envelope> repo)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_repo = repo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public async Task<IEnumerable<EnvelopeDto>> Handle(ReadEnvelopeQuery request, CancellationToken cancel)
|
||||
{
|
||||
var envelopesQ = _repo.Query.Where(request, notnull: false);
|
||||
|
||||
EnvelopeStatusQuery? statusQ = request.Status;
|
||||
bool? hasDocResult = request.HasDocResult;
|
||||
|
||||
var filtered =
|
||||
from envelope in envelopesQ
|
||||
where (statusQ == null || statusQ.Include == null || statusQ.Include.Contains(envelope.Status))
|
||||
&& (statusQ == null || statusQ.Ignore == null || !statusQ.Ignore.Contains(envelope.Status))
|
||||
&& (statusQ == null || statusQ.Min == null || envelope.Status > statusQ.Min)
|
||||
&& (statusQ == null || statusQ.Max == null || envelope.Status < statusQ.Max)
|
||||
&& (!hasDocResult.HasValue || (hasDocResult.Value ? envelope.DocResult != null : envelope.DocResult == null))
|
||||
select envelope;
|
||||
|
||||
var envelopes = await filtered.ToListAsync(cancel);
|
||||
|
||||
return _mapper.Map<IEnumerable<EnvelopeDto>>(envelopes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace EnvelopeGenerator.Application.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class BurnAnnotationException : ApplicationException
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public BurnAnnotationException(string message)
|
||||
: base(message) { }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public BurnAnnotationException(string message, Exception innerException)
|
||||
: base(message, innerException) { }
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class CreateReportException : ApplicationException
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public CreateReportException(string message)
|
||||
: base(message) { }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="innerException"></param>
|
||||
public CreateReportException(string message, Exception innerException)
|
||||
: base(message, innerException) { }
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace EnvelopeGenerator.Application.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ExportDocumentException : ApplicationException
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public ExportDocumentException(string message)
|
||||
: base(message) { }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="innerException"></param>
|
||||
public ExportDocumentException(string message, Exception innerException)
|
||||
: base(message, innerException) { }
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace EnvelopeGenerator.Application.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class MergeDocumentException : ApplicationException
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public MergeDocumentException(string message)
|
||||
: base(message) { }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="innerException"></param>
|
||||
public MergeDocumentException(string message, Exception innerException)
|
||||
: base(message, innerException) { }
|
||||
}
|
||||
@@ -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>
|
||||
///
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Histories.Queries;
|
||||
|
||||
//TODO: Add sender query
|
||||
/// <summary>
|
||||
/// Repräsentiert eine Abfrage für die Verlaufshistorie eines Umschlags.
|
||||
/// </summary>
|
||||
public record CountHistoryQuery : HistoryQueryBase, IRequest<int>;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class CountHistoryQueryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="uuid"></param>
|
||||
/// <param name="statuses"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<bool> AnyHistoryAsync(this ISender sender, string uuid, IEnumerable<EnvelopeStatus> statuses, CancellationToken cancel = default)
|
||||
{
|
||||
var count = await sender.Send(new CountHistoryQuery
|
||||
{
|
||||
Envelope = new() { Uuid = uuid },
|
||||
Statuses = new() { Include = statuses }
|
||||
}, cancel);
|
||||
return count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class CountHistoryQueryHandler : IRequestHandler<CountHistoryQuery, int>
|
||||
{
|
||||
private readonly IRepository<History> _repo;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repo"></param>
|
||||
public CountHistoryQueryHandler(IRepository<History> repo)
|
||||
{
|
||||
_repo = repo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotFoundException"></exception>
|
||||
public Task<int> Handle(CountHistoryQuery request, CancellationToken cancel = default)
|
||||
{
|
||||
var query = _repo.Query;
|
||||
|
||||
if (request.Envelope.Id is int envId)
|
||||
query = query.Where(e => e.Id == envId);
|
||||
else if (request.Envelope.Uuid is string uuid)
|
||||
query = query.Where(e => e.Envelope!.Uuid == uuid);
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
else if (request.EnvelopeId is not null)
|
||||
query = query.Where(h => h.EnvelopeId == request.EnvelopeId);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
else
|
||||
throw new BadRequestException("Invalid request: An Envelope object or a valid EnvelopeId/UUID must be supplied.");
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
if (request.Status is not null)
|
||||
query = query.Where(h => h.Status == request.Status);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
if (request.Statuses is not null)
|
||||
{
|
||||
var status = request.Statuses;
|
||||
if (status.Min is not null)
|
||||
query = query.Where(er => er.Envelope!.Status >= status.Min);
|
||||
|
||||
if (status.Max is not null)
|
||||
query = query.Where(er => er.Envelope!.Status <= status.Max);
|
||||
|
||||
if (status.Include?.Count() > 0)
|
||||
query = query.Where(er => status.Include.Contains(er.Envelope!.Status));
|
||||
|
||||
if (status.Ignore is not null)
|
||||
query = query.Where(er => !status.Ignore.Contains(er.Envelope!.Status));
|
||||
}
|
||||
|
||||
return query.CountAsync(cancel);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
using EnvelopeGenerator.Application.Common.Query;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Histories.Queries;
|
||||
|
||||
//TODO: Add sender query
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record HistoryQueryBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Die eindeutige Kennung des Umschlags.
|
||||
/// </summary>
|
||||
[Obsolete("Use Envelope property")]
|
||||
public int? EnvelopeId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Include des Umschlags, der abgefragt werden soll. Kann optional angegeben werden, um die Ergebnisse zu filtern.
|
||||
/// </summary>
|
||||
[Obsolete("Use statuses")]
|
||||
public EnvelopeStatus? Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public EnvelopeStatusQuery Statuses { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public EnvelopeQueryBase Envelope { get; set; } = new EnvelopeQueryBase();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record EnvelopeStatusQuery
|
||||
{
|
||||
/// <summary>
|
||||
/// Der minimale Statuswert, der berücksichtigt werden.
|
||||
/// </summary>
|
||||
public EnvelopeStatus? Min { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Der maximale Statuswert, der berücksichtigt werden.
|
||||
/// </summary>
|
||||
public EnvelopeStatus? Max { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Eine Liste von Statuswerten, die einbezogen werden.
|
||||
/// </summary>
|
||||
public IEnumerable<EnvelopeStatus>? Include { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Eine Liste von Statuswerten, die ignoriert werden werden.
|
||||
/// </summary>
|
||||
public IEnumerable<EnvelopeStatus>? Ignore { get; init; }
|
||||
}
|
||||
@@ -1,10 +1,7 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using EnvelopeGenerator.Application.Common.Dto.History;
|
||||
using EnvelopeGenerator.Application.Common.Dto.History;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using MediatR;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Histories.Queries;
|
||||
|
||||
@@ -12,81 +9,21 @@ namespace EnvelopeGenerator.Application.Histories.Queries;
|
||||
/// <summary>
|
||||
/// Repräsentiert eine Abfrage für die Verlaufshistorie eines Umschlags.
|
||||
/// </summary>
|
||||
public record ReadHistoryQuery : HistoryQueryBase, IRequest<IEnumerable<HistoryDto>>
|
||||
public record ReadHistoryQuery : IRequest<IEnumerable<HistoryDto>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Die eindeutige Kennung des Umschlags.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int EnvelopeId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Include des Umschlags, der abgefragt werden soll. Kann optional angegeben werden, um die Ergebnisse zu filtern.
|
||||
/// </summary>
|
||||
public EnvelopeStatus? Status { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Abfrage zur Steuerung, ob nur der aktuelle Include oder der gesamte Datensatz zurückgegeben wird.
|
||||
/// </summary>
|
||||
public bool OnlyLast { get; init; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadHistoryQueryHandler : IRequestHandler<ReadHistoryQuery, IEnumerable<HistoryDto>>
|
||||
{
|
||||
private readonly IRepository<History> _repo;
|
||||
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repo"></param>
|
||||
/// <param name="mapper"></param>
|
||||
public ReadHistoryQueryHandler(IRepository<History> repo, IMapper mapper)
|
||||
{
|
||||
_repo = repo;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotFoundException"></exception>
|
||||
public async Task<IEnumerable<HistoryDto>> Handle(ReadHistoryQuery request, CancellationToken cancel = default)
|
||||
{
|
||||
var query = _repo.Query;
|
||||
|
||||
if (request.Envelope.Id is int envId)
|
||||
query = query.Where(e => e.Id == envId);
|
||||
else if (request.Envelope.Uuid is string uuid)
|
||||
query = query.Where(e => e.Envelope!.Uuid == uuid);
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
else if (request.EnvelopeId is not null)
|
||||
query = query.Where(h => h.EnvelopeId == request.EnvelopeId);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
else
|
||||
throw new BadRequestException("Invalid request: An Envelope object or a valid EnvelopeId/UUID must be supplied.");
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
if (request.Status is not null)
|
||||
query = query.Where(h => h.Status == request.Status);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
if (request.Statuses is not null)
|
||||
{
|
||||
var status = request.Statuses;
|
||||
if (status.Min is not null)
|
||||
query = query.Where(er => er.Envelope!.Status >= status.Min);
|
||||
|
||||
if (status.Max is not null)
|
||||
query = query.Where(er => er.Envelope!.Status <= status.Max);
|
||||
|
||||
if (status.Include?.Count() > 0)
|
||||
query = query.Where(er => status.Include.Contains(er.Envelope!.Status));
|
||||
|
||||
if (status.Ignore is not null)
|
||||
query = query.Where(er => !status.Ignore.Contains(er.Envelope!.Status));
|
||||
}
|
||||
|
||||
if (request.OnlyLast)
|
||||
query = query.OrderByDescending(x => x.AddedWhen);
|
||||
|
||||
var hists = await query.ToListAsync(cancel);
|
||||
return _mapper.Map<List<HistoryDto>>(hists);
|
||||
}
|
||||
public bool? OnlyLast { get; init; } = true;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using EnvelopeGenerator.Application.Common.Dto.History;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Histories.Queries;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadHistoryQueryHandler : IRequestHandler<ReadHistoryQuery, IEnumerable<HistoryDto>>
|
||||
{
|
||||
private readonly IRepository<History> _repo;
|
||||
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repo"></param>
|
||||
/// <param name="mapper"></param>
|
||||
public ReadHistoryQueryHandler(IRepository<History> repo, IMapper mapper)
|
||||
{
|
||||
_repo = repo;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotFoundException"></exception>
|
||||
public async Task<IEnumerable<HistoryDto>> Handle(ReadHistoryQuery request, CancellationToken cancel = default)
|
||||
{
|
||||
var query = _repo.ReadOnly().Where(h => h.EnvelopeId == request.EnvelopeId);
|
||||
if (request.Status is not null)
|
||||
query = query.Where(h => h.Status == request.Status);
|
||||
|
||||
var hists = await query.ToListAsync(cancel);
|
||||
return _mapper.Map<List<HistoryDto>>(hists);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
#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 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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
113
EnvelopeGenerator.Application/Pdf/Behaviors/SendEmailBehavior.cs
Normal file
113
EnvelopeGenerator.Application/Pdf/Behaviors/SendEmailBehavior.cs
Normal 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;
|
||||
}
|
||||
@@ -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
|
||||
305
EnvelopeGenerator.Application/Pdf/BurnPdfCommand.cs
Normal file
305
EnvelopeGenerator.Application/Pdf/BurnPdfCommand.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Application.Common.Dto;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace EnvelopeGenerator.Application.ThirdPartyModules.Queries;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record ReadThirdPartyModuleQuery : IRequest<IEnumerable<ThirdPartyModuleDto>>
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool? Active { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record ReadThirdPartyModuleQueryHandler : IRequestHandler<ReadThirdPartyModuleQuery, IEnumerable<ThirdPartyModuleDto>>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
private readonly IRepository<ThirdPartyModule> _repo;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="mapper"></param>
|
||||
/// <param name="repo"></param>
|
||||
public ReadThirdPartyModuleQueryHandler(IMapper mapper, IRepository<ThirdPartyModule> repo)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_repo = repo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public async Task<IEnumerable<ThirdPartyModuleDto>> Handle(ReadThirdPartyModuleQuery request, CancellationToken cancel)
|
||||
{
|
||||
var query = _repo.Query;
|
||||
|
||||
if(request.Name is string name)
|
||||
query = query.Where(m => m.Name == name);
|
||||
|
||||
if (request.Active is bool active)
|
||||
query = query.Where(m => m.Active == active);
|
||||
|
||||
var modules = await query.ToListAsync(cancel);
|
||||
|
||||
return _mapper.Map<IEnumerable<ThirdPartyModuleDto>>(modules);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class ReadThirdPartyModuleQueryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="mediator"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="active"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string?> ReadThirdPartyModuleLicenseAsync(this IMediator mediator, string name, bool active = true, CancellationToken cancel = default)
|
||||
{
|
||||
var modules = await mediator.Send(new ReadThirdPartyModuleQuery()
|
||||
{
|
||||
Name = name,
|
||||
Active = active,
|
||||
}, cancel);
|
||||
|
||||
return modules.FirstOrDefault()?.License;
|
||||
}
|
||||
}
|
||||
@@ -70,8 +70,8 @@
|
||||
<Reference Include="DigitalData.Controls.DocumentViewer, Version=1.9.8.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DigitalData.Controls.DocumentViewer.1.9.8\lib\net462\DigitalData.Controls.DocumentViewer.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DigitalData.Core.Abstraction.Application, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DigitalData.Core.Abstraction.Application.1.4.0\lib\net462\DigitalData.Core.Abstraction.Application.dll</HintPath>
|
||||
<Reference Include="DigitalData.Core.Abstraction.Application, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DigitalData.Core.Abstraction.Application.1.5.0\lib\net462\DigitalData.Core.Abstraction.Application.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DigitalData.Core.Abstractions, Version=4.3.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DigitalData.Core.Abstractions.4.3.0\lib\net462\DigitalData.Core.Abstractions.dll</HintPath>
|
||||
|
||||
@@ -32,7 +32,7 @@ Public Class frmFinalizePDF
|
||||
#Disable Warning BC40000 ' Type or member is obsolete
|
||||
Factory.Shared _
|
||||
.BehaveOnPostBuild(PostBuildBehavior.Ignore) _
|
||||
.AddEnvelopeGeneratorInfrastructureServices(
|
||||
.AddEGInfrastructureServices(
|
||||
Sub(opt)
|
||||
opt.AddDbTriggerParams(
|
||||
Sub(triggers)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<package id="AutoMapper" version="10.1.1" targetFramework="net462" />
|
||||
<package id="BouncyCastle.Cryptography" version="2.5.0" targetFramework="net462" />
|
||||
<package id="DigitalData.Controls.DocumentViewer" version="1.9.8" targetFramework="net462" />
|
||||
<package id="DigitalData.Core.Abstraction.Application" version="1.4.0" targetFramework="net462" />
|
||||
<package id="DigitalData.Core.Abstraction.Application" version="1.5.0" targetFramework="net462" />
|
||||
<package id="DigitalData.Core.Abstractions" version="4.3.0" targetFramework="net462" />
|
||||
<package id="DigitalData.Modules.Base" version="1.3.8" targetFramework="net462" />
|
||||
<package id="DigitalData.Modules.Config" version="1.3.0" targetFramework="net462" />
|
||||
|
||||
@@ -72,8 +72,8 @@
|
||||
<Reference Include="DevExpress.XtraEditors.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
|
||||
<Reference Include="DevExpress.XtraGauges.v21.2.Core, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL" />
|
||||
<Reference Include="DevExpress.XtraReports.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL" />
|
||||
<Reference Include="DigitalData.Core.Abstraction.Application, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DigitalData.Core.Abstraction.Application.1.4.0\lib\net462\DigitalData.Core.Abstraction.Application.dll</HintPath>
|
||||
<Reference Include="DigitalData.Core.Abstraction.Application, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DigitalData.Core.Abstraction.Application.1.5.0\lib\net462\DigitalData.Core.Abstraction.Application.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DigitalData.Core.Abstractions, Version=4.3.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DigitalData.Core.Abstractions.4.3.0\lib\net462\DigitalData.Core.Abstractions.dll</HintPath>
|
||||
@@ -560,10 +560,6 @@
|
||||
<Project>{4f32a98d-e6f0-4a09-bd97-1cf26107e837}</Project>
|
||||
<Name>EnvelopeGenerator.Domain</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj">
|
||||
<Project>{63e32615-0eca-42dc-96e3-91037324b7c7}</Project>
|
||||
<Name>EnvelopeGenerator.Infrastructure</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\EnvelopeGenerator.PdfEditor\EnvelopeGenerator.PdfEditor.csproj">
|
||||
<Project>{211619f5-ae25-4ba5-a552-bacafe0632d3}</Project>
|
||||
<Name>EnvelopeGenerator.PdfEditor</Name>
|
||||
|
||||
@@ -69,28 +69,28 @@ Namespace Jobs
|
||||
Dim oConnectionString As String = pContext.MergedJobDataMap.Item(Value.DATABASE)
|
||||
Database = New MSSQLServer(LogConfig, MSSQLServer.DecryptConnectionString(oConnectionString))
|
||||
|
||||
#Disable Warning BC40000 ' Type or member is obsolete
|
||||
Factory.Shared _
|
||||
.BehaveOnPostBuild(PostBuildBehavior.Ignore) _
|
||||
.AddEnvelopeGeneratorInfrastructureServices(
|
||||
Sub(opt)
|
||||
opt.AddDbTriggerParams(
|
||||
Sub(triggers)
|
||||
triggers("Envelope") = New List(Of String) From {"TBSIG_ENVELOPE_AFT_INS"}
|
||||
triggers("History") = New List(Of String) From {"TBSIG_ENVELOPE_HISTORY_AFT_INS"}
|
||||
triggers("EmailOut") = New List(Of String) From {"TBEMLP_EMAIL_OUT_AFT_INS", "TBEMLP_EMAIL_OUT_AFT_UPD"}
|
||||
triggers("EnvelopeReceiverReadOnly") = New List(Of String) From {"TBSIG_ENVELOPE_RECEIVER_READ_ONLY_UPD"}
|
||||
triggers("Receiver") = New List(Of String)() ' no tigger
|
||||
triggers("EmailTemplate") = New List(Of String) From {"TBSIG_EMAIL_TEMPLATE_AFT_UPD"}
|
||||
End Sub)
|
||||
opt.AddDbContext(
|
||||
Sub(options)
|
||||
options.UseSqlServer(oConnectionString) _
|
||||
.EnableSensitiveDataLogging() _
|
||||
.EnableDetailedErrors()
|
||||
End Sub)
|
||||
End Sub)
|
||||
#Enable Warning BC40000 ' Type or member is obsolete
|
||||
'#Disable Warning BC40000 ' Type or member is obsolete
|
||||
' Factory.Shared _
|
||||
' .BehaveOnPostBuild(PostBuildBehavior.Ignore) _
|
||||
' .AddEGInfrastructureServices(
|
||||
' Sub(opt)
|
||||
' opt.AddDbTriggerParams(
|
||||
' Sub(triggers)
|
||||
' triggers("Envelope") = New List(Of String) From {"TBSIG_ENVELOPE_AFT_INS"}
|
||||
' triggers("History") = New List(Of String) From {"TBSIG_ENVELOPE_HISTORY_AFT_INS"}
|
||||
' triggers("EmailOut") = New List(Of String) From {"TBEMLP_EMAIL_OUT_AFT_INS", "TBEMLP_EMAIL_OUT_AFT_UPD"}
|
||||
' triggers("EnvelopeReceiverReadOnly") = New List(Of String) From {"TBSIG_ENVELOPE_RECEIVER_READ_ONLY_UPD"}
|
||||
' triggers("Receiver") = New List(Of String)() ' no tigger
|
||||
' triggers("EmailTemplate") = New List(Of String) From {"TBSIG_EMAIL_TEMPLATE_AFT_UPD"}
|
||||
' End Sub)
|
||||
' opt.AddDbContext(
|
||||
' Sub(options)
|
||||
' options.UseSqlServer(oConnectionString) _
|
||||
' .EnableSensitiveDataLogging() _
|
||||
' .EnableDetailedErrors()
|
||||
' End Sub)
|
||||
' End Sub)
|
||||
'#Enable Warning BC40000 ' Type or member is obsolete
|
||||
|
||||
Logger.Debug("Loading Models & Services")
|
||||
Dim oState = GetState()
|
||||
|
||||
@@ -55,7 +55,7 @@ Public Class PDFMerger
|
||||
End If
|
||||
|
||||
' Convert to PDF/A
|
||||
oMergedPDF.ConvertToPDFA(oFinalStream, PDFAConformanceLevel, ALLOW_VECTORIZATION, ALLOW_RASTERIZATION)
|
||||
oMergedPDF.SaveToStream(oFinalStream)
|
||||
oStatus = oDocumentPDF.GetStat()
|
||||
If oStatus <> GdPictureStatus.OK Then
|
||||
Throw New MergeDocumentException($"Document could not be converted to PDF/A: {oStatus}")
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<packages>
|
||||
<package id="AutoMapper" version="10.1.1" targetFramework="net462" />
|
||||
<package id="BouncyCastle.Cryptography" version="2.5.0" targetFramework="net462" />
|
||||
<package id="DigitalData.Core.Abstraction.Application" version="1.4.0" targetFramework="net462" />
|
||||
<package id="DigitalData.Core.Abstraction.Application" version="1.5.0" targetFramework="net462" />
|
||||
<package id="DigitalData.Core.Abstractions" version="4.3.0" targetFramework="net462" />
|
||||
<package id="DigitalData.Modules.Base" version="1.3.8" targetFramework="net462" />
|
||||
<package id="DigitalData.Modules.Config" version="1.3.0" targetFramework="net462" />
|
||||
|
||||
98
EnvelopeGenerator.DependencyInjection/DependencyInjection.cs
Normal file
98
EnvelopeGenerator.DependencyInjection/DependencyInjection.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
using DigitalData.EmailProfilerDispatcher;
|
||||
using DigitalData.UserManager.DependencyInjection;
|
||||
using EnvelopeGenerator.Application;
|
||||
using EnvelopeGenerator.Infrastructure;
|
||||
using Microsoft.Extensions.Caching.SqlServer;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using static EnvelopeGenerator.Infrastructure.DependencyInjection;
|
||||
|
||||
namespace EnvelopeGenerator.DependencyInjection;
|
||||
|
||||
public static class DependencyInjection
|
||||
{
|
||||
public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, Action<EGConfiguration> options)
|
||||
{
|
||||
var egConfig = new EGConfiguration();
|
||||
options.Invoke(egConfig);
|
||||
egConfig.EnsureAllServicesConfigured();
|
||||
egConfig.RegisterAll(services);
|
||||
|
||||
// Add envelope generator services
|
||||
#pragma warning disable CS0618
|
||||
services.AddUserManager<EGDbContext>();
|
||||
#pragma warning restore CS0618
|
||||
|
||||
services.AddDispatcher<EGDbContext>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public record EGConfiguration
|
||||
{
|
||||
internal readonly Queue<Action<IServiceCollection>> _serviceRegs = new();
|
||||
|
||||
internal void RegisterAll(IServiceCollection services)
|
||||
{
|
||||
while (_serviceRegs.Count > 0)
|
||||
_serviceRegs.Dequeue().Invoke(services);
|
||||
}
|
||||
|
||||
// TODO: update to use attributes and reflections instead of _addingStatus-dictionary
|
||||
private readonly Dictionary<string, bool> _addingStatus = new ()
|
||||
{
|
||||
{ nameof(AddLocalization), false },
|
||||
{ nameof(AddDistributedSqlServerCache), false },
|
||||
{ nameof(AddInfrastructure), false },
|
||||
{ nameof(AddServices), false },
|
||||
};
|
||||
|
||||
public EGConfiguration AddLocalization(Action<IServiceCollection>? customLocalizationOptions = null)
|
||||
{
|
||||
_serviceRegs.Enqueue(customLocalizationOptions ?? (s => s.AddLocalization()));
|
||||
_addingStatus[nameof(AddLocalization)] = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EGConfiguration AddDistributedSqlServerCache(Action<SqlServerCacheOptions> setupAction)
|
||||
{
|
||||
_serviceRegs.Enqueue(s => s.AddDistributedSqlServerCache(setupAction));
|
||||
_addingStatus[nameof(AddDistributedSqlServerCache)] = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EGConfiguration AddInfrastructure(Action<EGInfrastructureConfiguration> options)
|
||||
{
|
||||
#pragma warning disable CS0618
|
||||
_serviceRegs.Enqueue(s => s.AddEGInfrastructureServices(options));
|
||||
#pragma warning restore CS0618
|
||||
_addingStatus[nameof(AddInfrastructure)] = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EGConfiguration AddServices(IConfiguration config, bool usePdfBurner = false)
|
||||
{
|
||||
#pragma warning disable CS0618
|
||||
_serviceRegs.Enqueue(s => s.AddEnvelopeGeneratorServices(config));
|
||||
#pragma warning restore CS0618
|
||||
_addingStatus[nameof(AddServices)] = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
internal void EnsureAllServicesConfigured()
|
||||
{
|
||||
var missingServices = _addingStatus
|
||||
.Where(kv => !kv.Value)
|
||||
.Select(kv => kv.Key)
|
||||
.ToList();
|
||||
|
||||
if (missingServices.Count > 0)
|
||||
{
|
||||
var missingList = string.Join(", ", missingServices);
|
||||
throw new InvalidOperationException(
|
||||
$"Service configuration incomplete. The following required service methods were not called: {missingList}. " +
|
||||
"Please ensure all necessary configuration methods are invoked before building the application.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="9.0.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.10" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Application\EnvelopeGenerator.Application.csproj" />
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
13
EnvelopeGenerator.Domain/Constants/AnnotationType.cs
Normal file
13
EnvelopeGenerator.Domain/Constants/AnnotationType.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace EnvelopeGenerator.Domain.Constants
|
||||
{
|
||||
public static class AnnotationType
|
||||
{
|
||||
public static class PSPDFKit
|
||||
{
|
||||
public const string Image = "pspdfkit/image";
|
||||
public const string Ink = "pspdfkit/ink";
|
||||
public const string Widget = "pspdfkit/widget";
|
||||
public const string FormField = "pspdfkit/form-field-value";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
|
||||
#if NETFRAMEWORK
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -134,14 +133,12 @@ public class Envelope
|
||||
= false;
|
||||
#endif
|
||||
|
||||
[NotMapped]
|
||||
[Column("DOC_RESULT")]
|
||||
public byte[]
|
||||
#if NET
|
||||
?
|
||||
#endif
|
||||
DocResult
|
||||
{ get; set; }
|
||||
DocResult { get; set; }
|
||||
|
||||
[ForeignKey("EnvelopeTypeId")]
|
||||
public virtual EnvelopeType
|
||||
|
||||
36
EnvelopeGenerator.Domain/Entities/EnvelopeReport.cs
Normal file
36
EnvelopeGenerator.Domain/Entities/EnvelopeReport.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
#if NETFRAMEWORK
|
||||
using System;
|
||||
#endif
|
||||
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
{
|
||||
[Table("VWSIG_ENVELOPE_REPORT", Schema = "dbo")]
|
||||
public class EnvelopeReport
|
||||
{
|
||||
[Key]
|
||||
[Column("ENVELOPE_ID")]
|
||||
public int EnvelopeId { get; set; }
|
||||
|
||||
// --- HEAD ---
|
||||
[Column("HEAD_UUID")]
|
||||
public string HeadUuid { get; set; }
|
||||
|
||||
[Column("HEAD_TITLE")]
|
||||
public string EnvelopeTitle { get; set; } = string.Empty;
|
||||
|
||||
[Column("HEAD_MESSAGE")]
|
||||
public string HeadMessage { get; set; }
|
||||
|
||||
// --- POSITIONS ---
|
||||
[Column("POS_STATUS")]
|
||||
public int ItemStatus { get; set; }
|
||||
|
||||
[Column("POS_WHEN")]
|
||||
public DateTime? ItemDate { get; set; }
|
||||
|
||||
[Column("POS_WHO")]
|
||||
public string ItemUserReference { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@ using System.ComponentModel.DataAnnotations.Schema;
|
||||
#if NETFRAMEWORK
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#elif NET
|
||||
using System.Text.Json.Serialization;
|
||||
#endif
|
||||
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
@@ -120,13 +122,17 @@ public class Signature : ISignature, IHasReceiver
|
||||
#endif
|
||||
Annotations { get; set; }
|
||||
|
||||
#if NETFRAMEWORK
|
||||
#if NET
|
||||
[JsonIgnore]
|
||||
#endif
|
||||
[NotMapped]
|
||||
public double Top => Math.Round(Y, 5);
|
||||
|
||||
#if NET
|
||||
[JsonIgnore]
|
||||
#endif
|
||||
[NotMapped]
|
||||
public double Left => Math.Round(X, 5);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETFRAMEWORK
|
||||
|
||||
73
EnvelopeGenerator.Domain/Entities/ThirdPartyModule.cs
Normal file
73
EnvelopeGenerator.Domain/Entities/ThirdPartyModule.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
#if NETFRAMEWORK
|
||||
using System;
|
||||
#endif
|
||||
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
{
|
||||
[Table("TBDD_3RD_PARTY_MODULES")]
|
||||
public class ThirdPartyModule
|
||||
{
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
[Column("GUID")]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("ACTIVE")]
|
||||
public bool Active { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(50)]
|
||||
[Column("NAME")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[StringLength(500)]
|
||||
[Column("DESCRIPTION")]
|
||||
public string
|
||||
#if nullable
|
||||
?
|
||||
#endif
|
||||
Description { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("LICENSE", TypeName = "varchar(max)")]
|
||||
public string License { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(20)]
|
||||
[Column("VERSION")]
|
||||
public string Version { get; set; }
|
||||
|
||||
[StringLength(50)]
|
||||
[Column("ADDED_WHO")]
|
||||
public string
|
||||
#if nullable
|
||||
?
|
||||
#endif
|
||||
AddedWho { get; set; }
|
||||
|
||||
[Column("ADDED_WHEN")]
|
||||
public DateTime
|
||||
#if nullable
|
||||
?
|
||||
#endif
|
||||
AddedWhen { get; set; }
|
||||
|
||||
[StringLength(50)]
|
||||
[Column("CHANGED_WHO")]
|
||||
public string
|
||||
#if nullable
|
||||
?
|
||||
#endif
|
||||
ChangedWho { get; set; }
|
||||
|
||||
[Column("CHANGED_WHEN")]
|
||||
public DateTime
|
||||
#if nullable
|
||||
?
|
||||
#endif
|
||||
ChangedWhen { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UserSecretsId>dotnet-EnvelopeGenerator.Finalizer-6d5cc618-4159-4ff2-b600-8a15fbfa8099</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!--<PackageReference Include="DevExpress.Reporting.Core" Version="25.1.6" />
|
||||
<PackageReference Include="DevExpress.Win.Navigation" Version="25.1.6" />-->
|
||||
<PackageReference Include="Quartz.AspNetCore" Version="3.15.1" />
|
||||
<PackageReference Include="Quartzmon" Version="1.0.5" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
|
||||
<PackageReference Include="Quartz" Version="3.15.1" />
|
||||
<PackageReference Include="Quartz.Extensions.Hosting" Version="3.15.1" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Application\EnvelopeGenerator.Application.csproj" />
|
||||
<ProjectReference Include="..\EnvelopeGenerator.DependencyInjection\EnvelopeGenerator.DependencyInjection.csproj" />
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Controllers\" />
|
||||
<Folder Include="Controllers\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="appsettings.Database.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="appsettings.Logging.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
35
EnvelopeGenerator.Finalizer/Extensions.cs
Normal file
35
EnvelopeGenerator.Finalizer/Extensions.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using EnvelopeGenerator.Finalizer.Job;
|
||||
using Quartz;
|
||||
|
||||
namespace EnvelopeGenerator.Finalizer;
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
public static IServiceCollectionQuartzConfigurator ScheduleJobDefault<TJob>(this IServiceCollectionQuartzConfigurator q,
|
||||
string croneEpression)
|
||||
where TJob : IJob
|
||||
{
|
||||
var name = $"{typeof(TJob).FullName}";
|
||||
var jobKey = new JobKey(name);
|
||||
|
||||
return q.ScheduleJob<TJob>(trigger => trigger
|
||||
.WithIdentity(name + "-trigger")
|
||||
.WithCronSchedule(croneEpression),
|
||||
job => job.WithIdentity(jobKey)
|
||||
);
|
||||
}
|
||||
|
||||
public static IServiceCollectionQuartzConfigurator ScheduleJobDefault<TJob>(this IServiceCollectionQuartzConfigurator q,
|
||||
IConfiguration configuration)
|
||||
where TJob : IJob
|
||||
{
|
||||
var expression = configuration[$"{typeof(TJob).Name}:CronExpression"];
|
||||
if (string.IsNullOrWhiteSpace(expression))
|
||||
throw new InvalidOperationException(
|
||||
"Cron expression for the Worker job is not configured. " +
|
||||
"Please provide a valid cron schedule in the configuration under " +
|
||||
$"'{typeof(TJob).FullName}:CronExpression'.");
|
||||
|
||||
return q.ScheduleJobDefault<TJob>(expression);
|
||||
}
|
||||
}
|
||||
24
EnvelopeGenerator.Finalizer/Job/EnvelopeTaskApiJob.cs
Normal file
24
EnvelopeGenerator.Finalizer/Job/EnvelopeTaskApiJob.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using Quartz;
|
||||
|
||||
namespace EnvelopeGenerator.Finalizer.Job
|
||||
{
|
||||
public class EnvelopeTaskApiJob : IJob
|
||||
{
|
||||
private readonly ILogger<EnvelopeTaskApiJob> _logger;
|
||||
|
||||
public EnvelopeTaskApiJob(ILogger<EnvelopeTaskApiJob> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
if (_logger.IsEnabled(LogLevel.Information))
|
||||
{
|
||||
_logger.LogInformation("{jobName} running at: {time}", context.JobDetail.Key, DateTimeOffset.Now);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
72
EnvelopeGenerator.Finalizer/Job/FinishEnvelopeJob.cs
Normal file
72
EnvelopeGenerator.Finalizer/Job/FinishEnvelopeJob.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using EnvelopeGenerator.Application.Common.Configurations;
|
||||
using EnvelopeGenerator.Application.Envelopes.Queries;
|
||||
using EnvelopeGenerator.Application.Pdf;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Quartz;
|
||||
|
||||
namespace EnvelopeGenerator.Finalizer.Job
|
||||
{
|
||||
public class FinishEnvelopeJob : IJob
|
||||
{
|
||||
private readonly ILogger<FinishEnvelopeJob> _logger;
|
||||
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
private readonly PDFBurnerParams _options;
|
||||
|
||||
public FinishEnvelopeJob(ILogger<FinishEnvelopeJob> logger, IMediator mediator, IOptions<PDFBurnerParams> options)
|
||||
{
|
||||
_logger = logger;
|
||||
_mediator = mediator;
|
||||
_options = options.Value;
|
||||
}
|
||||
|
||||
public async Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
var cancel = context.CancellationToken;
|
||||
|
||||
var envelopes = await _mediator.Send(new ReadEnvelopeQuery()
|
||||
{
|
||||
Status = new() { Include = [ EnvelopeStatus.EnvelopeCompletelySigned ] },
|
||||
HasDocResult = false
|
||||
}, cancel);
|
||||
|
||||
using var semaphore = new SemaphoreSlim(_options.ConcurrencyLimit);
|
||||
await Task.WhenAll(envelopes.Select(async envelope =>
|
||||
{
|
||||
await semaphore.WaitAsync(cancel);
|
||||
try
|
||||
{
|
||||
await _mediator.BurnPdf(envelope.Id, cancel);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error burning envelope {EnvelopeId}", envelope.Id);
|
||||
}
|
||||
finally
|
||||
{
|
||||
semaphore.Release();
|
||||
}
|
||||
}));
|
||||
|
||||
var envelopeCount = envelopes.Count();
|
||||
if (envelopeCount > 0)
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Job '{JobName}' executed at {Timestamp}. {EnvelopeCount} envelope(s) successfully finalized. UUID(s): {EnvelopeUuids}",
|
||||
context.JobDetail.Key.Name,
|
||||
context.FireTimeUtc.ToLocalTime(),
|
||||
envelopeCount,
|
||||
string.Join(", ", envelopes.Select(e => e.Uuid))
|
||||
);
|
||||
}
|
||||
else
|
||||
_logger.LogInformation("Job '{JobName}' executed successfully at {Timestamp}. No envelopes were finalized.",
|
||||
context.JobDetail.Key.Name,
|
||||
context.FireTimeUtc.ToLocalTime()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
129
EnvelopeGenerator.Finalizer/Program.cs
Normal file
129
EnvelopeGenerator.Finalizer/Program.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
using EnvelopeGenerator.DependencyInjection;
|
||||
using EnvelopeGenerator.Finalizer;
|
||||
using EnvelopeGenerator.Finalizer.Job;
|
||||
using EnvelopeGenerator.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Quartz;
|
||||
using Quartz.AspNetCore;
|
||||
using Quartzmon;
|
||||
using Serilog;
|
||||
|
||||
// Load Serilog from appsettings.json
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.ReadFrom.Configuration(new ConfigurationBuilder()
|
||||
.AddJsonFile("appsettings.Logging.json", optional: false, reloadOnChange: true)
|
||||
.Build())
|
||||
.CreateLogger();
|
||||
|
||||
try
|
||||
{
|
||||
Log.Information("Application is starting...");
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
#region Logging
|
||||
builder.Logging.ClearProviders();
|
||||
builder.Logging.AddSerilog();
|
||||
#endregion
|
||||
|
||||
#region Configuration
|
||||
var config = builder.Configuration;
|
||||
Directory
|
||||
.GetFiles(builder.Environment.ContentRootPath, "appsettings.*.json", SearchOption.TopDirectoryOnly)
|
||||
.Where(file => Path.GetFileName(file) != $"appsettings.Development.json")
|
||||
.Where(file => Path.GetFileName(file) != $"appsettings.migration.json")
|
||||
.ToList()
|
||||
.ForEach(file => config.AddJsonFile(file, true, true));
|
||||
#endregion
|
||||
|
||||
#region Web API Services
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
#endregion
|
||||
|
||||
#region Quartz
|
||||
builder.Services.AddQuartz(q =>
|
||||
{
|
||||
q.ScheduleJobDefault<FinishEnvelopeJob>(config);
|
||||
q.ScheduleJobDefault<EnvelopeTaskApiJob>(config);
|
||||
});
|
||||
|
||||
builder.Services.AddQuartzServer(options =>
|
||||
{
|
||||
options.WaitForJobsToComplete = true;
|
||||
});
|
||||
|
||||
builder.Services.AddQuartzmon();
|
||||
|
||||
builder.Services.AddSingleton(provider =>
|
||||
provider.GetRequiredService<ISchedulerFactory>().GetScheduler().Result
|
||||
);
|
||||
#endregion
|
||||
|
||||
#region Add DB Context, EG Inf. and Services
|
||||
var cnnStrName = "Default";
|
||||
var connStr = config.GetConnectionString(cnnStrName)
|
||||
?? throw new InvalidOperationException($"Connection string '{cnnStrName}' is missing in the application configuration.");
|
||||
|
||||
builder.Services.AddEnvelopeGenerator(egOptions => egOptions
|
||||
.AddLocalization()
|
||||
.AddDistributedSqlServerCache(options =>
|
||||
{
|
||||
options.ConnectionString = connStr;
|
||||
options.SchemaName = "dbo";
|
||||
options.TableName = "TBDD_CACHE";
|
||||
})
|
||||
.AddInfrastructure(opt =>
|
||||
{
|
||||
opt.AddDbTriggerParams(config);
|
||||
opt.AddDbContext((provider, options) =>
|
||||
{
|
||||
var logger = provider.GetRequiredService<ILogger<EGDbContext>>();
|
||||
var useInMemoryDb = config.GetValue<bool>("UseInMemoryDb");
|
||||
var dbCtxOpt = useInMemoryDb ? options.UseInMemoryDatabase("EGInMemoryDb") : options.UseSqlServer(connStr);
|
||||
dbCtxOpt.LogTo(log => logger.LogInformation("{log}", log), LogLevel.Trace)
|
||||
.EnableSensitiveDataLogging()
|
||||
.EnableDetailedErrors();
|
||||
});
|
||||
})
|
||||
.AddServices(config, true)
|
||||
);
|
||||
#endregion Add DB Context, EG Inf. and Services
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
#region Web API Middleware
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseAuthorization();
|
||||
|
||||
app.UseQuartzmon(new QuartzmonOptions()
|
||||
{
|
||||
Scheduler = app.Services.GetRequiredService<IScheduler>(),
|
||||
VirtualPathRoot = "/quartz"
|
||||
});
|
||||
|
||||
app.MapControllers();
|
||||
#endregion
|
||||
|
||||
app.Run();
|
||||
|
||||
Log.Information("The worker was stopped.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Fatal(ex, "Worker could not be started!");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Log.CloseAndFlush();
|
||||
}
|
||||
41
EnvelopeGenerator.Finalizer/Properties/launchSettings.json
Normal file
41
EnvelopeGenerator.Finalizer/Properties/launchSettings.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:17119",
|
||||
"sslPort": 44321
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "http://localhost:5010",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "quartz",
|
||||
"applicationUrl": "https://localhost:7141;http://localhost:5010",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": false,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
22
EnvelopeGenerator.Finalizer/appsettings.Database.json
Normal file
22
EnvelopeGenerator.Finalizer/appsettings.Database.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"UseDbMigration": false,
|
||||
"ConnectionStrings": {
|
||||
"Default": "Server=SDD-VMP04-SQL17\\DD_DEVELOP01;Database=DD_ECM;User Id=sa;Password=dd;Encrypt=false;TrustServerCertificate=True;",
|
||||
"DbMigrationTest": "Server=SDD-VMP04-SQL17\\DD_DEVELOP01;Database=DD_ECM_DATA_MIGR_TEST;User Id=sa;Password=dd;Encrypt=false;TrustServerCertificate=True;"
|
||||
},
|
||||
"DbTriggerParams": {
|
||||
"Envelope": [ "TBSIG_ENVELOPE_AFT_INS" ],
|
||||
"History": [ "TBSIG_ENVELOPE_HISTORY_AFT_INS" ],
|
||||
"EmailOut": [ "TBEMLP_EMAIL_OUT_AFT_INS", "TBEMLP_EMAIL_OUT_AFT_UPD" ],
|
||||
"EnvelopeReceiverReadOnly": [ "TBSIG_ENVELOPE_RECEIVER_READ_ONLY_UPD" ],
|
||||
"Receiver": [],
|
||||
"EmailTemplate": [ "TBSIG_EMAIL_TEMPLATE_AFT_UPD" ]
|
||||
},
|
||||
"UseInMemoryDb": false
|
||||
}
|
||||
9
EnvelopeGenerator.Finalizer/appsettings.Development.json
Normal file
9
EnvelopeGenerator.Finalizer/appsettings.Development.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Error",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"Debug": true
|
||||
}
|
||||
11
EnvelopeGenerator.Finalizer/appsettings.Job.json
Normal file
11
EnvelopeGenerator.Finalizer/appsettings.Job.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"FinishEnvelopeJob": {
|
||||
"CronExpression": "0 0/1 * 1/1 * ? *"
|
||||
},
|
||||
"EnvelopeTaskApiJob": {
|
||||
"CronExpression": "0 0/1 * 1/1 * ? *"
|
||||
},
|
||||
"Expressions": {
|
||||
"PerSec": "* * * * * ?"
|
||||
}
|
||||
}
|
||||
81
EnvelopeGenerator.Finalizer/appsettings.Logging.json
Normal file
81
EnvelopeGenerator.Finalizer/appsettings.Logging.json
Normal file
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"Serilog": {
|
||||
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
|
||||
"MinimumLevel": {
|
||||
"Default": "Verbose",
|
||||
"Override": {
|
||||
"Microsoft": "Warning",
|
||||
"System": "Warning"
|
||||
}
|
||||
},
|
||||
"WriteTo": [
|
||||
{
|
||||
"Name": "Console",
|
||||
"Args": {
|
||||
"outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "File",
|
||||
"Args": {
|
||||
"path": "E:/LogFiles/Digital Data/signFlow.Finalizer/log.Verbose-.txt",
|
||||
"rollingInterval": "Day",
|
||||
"restrictedToMinimumLevel": "Verbose",
|
||||
"retainedFileCountLimit": 30,
|
||||
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "File",
|
||||
"Args": {
|
||||
"path": "E:/LogFiles/Digital Data/signFlow.Finalizer/log.Debug-.txt",
|
||||
"rollingInterval": "Day",
|
||||
"restrictedToMinimumLevel": "Debug",
|
||||
"retainedFileCountLimit": 30,
|
||||
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "File",
|
||||
"Args": {
|
||||
"path": "E:/LogFiles/Digital Data/signFlow.Finalizer/log.Info-.txt",
|
||||
"rollingInterval": "Day",
|
||||
"restrictedToMinimumLevel": "Information",
|
||||
"retainedFileCountLimit": 30,
|
||||
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "File",
|
||||
"Args": {
|
||||
"path": "E:/LogFiles/Digital Data/signFlow.Finalizer/log.Warning-.txt",
|
||||
"rollingInterval": "Day",
|
||||
"restrictedToMinimumLevel": "Warning",
|
||||
"retainedFileCountLimit": 30,
|
||||
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "File",
|
||||
"Args": {
|
||||
"path": "E:/LogFiles/Digital Data/signFlow.Finalizer/log.Error-.txt",
|
||||
"rollingInterval": "Day",
|
||||
"restrictedToMinimumLevel": "Error",
|
||||
"retainedFileCountLimit": 30,
|
||||
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "File",
|
||||
"Args": {
|
||||
"path": "E:/LogFiles/Digital Data/signFlow.Finalizer/log.Fatal-.txt",
|
||||
"rollingInterval": "Day",
|
||||
"restrictedToMinimumLevel": "Fatal",
|
||||
"retainedFileCountLimit": 30,
|
||||
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
|
||||
}
|
||||
}
|
||||
],
|
||||
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
|
||||
}
|
||||
}
|
||||
14
EnvelopeGenerator.Finalizer/appsettings.PdfBurner.json
Normal file
14
EnvelopeGenerator.Finalizer/appsettings.PdfBurner.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"IgnoredLabels": {
|
||||
"Label": [
|
||||
"Date",
|
||||
"Datum",
|
||||
"ZIP",
|
||||
"PLZ",
|
||||
"Place",
|
||||
"Ort",
|
||||
"Position",
|
||||
"Stellung"
|
||||
]
|
||||
}
|
||||
}
|
||||
3
EnvelopeGenerator.Finalizer/appsettings.json
Normal file
3
EnvelopeGenerator.Finalizer/appsettings.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"GdPictureLicenseKey": "kG1Qf9PwmqgR8aDmIW2zI_ebj48RzqAJegRxcystEmkbTGQqfkNBdFOXIb6C_A00Ra8zZkrHdfjqzOPXK7kgkF2YDhvrqKfqh4WDug2vOt0qO31IommzkANSuLjZ4zmraoubyEVd25rE3veQ2h_j7tGIoH_LyIHmy24GaXsxdG0yCzIBMdiLbMMMDwcPY-809KeZ83Grv76OVhFvcbBWyYc251vou1N-kGg5_ZlHDgfWoY85gTLRxafjD3KS_i9ARW4BMiy36y8n7UP2jN8kGRnW_04ubpFtfjJqvtsrP_J9D0x7bqV8xtVtT5JI6dpKsVTiMgDCrIcoFSo5gCC1fw9oUopX4TDCkBQttO4-WHBlOeq9dG5Yb0otonVmJKaQA2tP6sMR-lZDs3ql_WI9t91yPWgpssrJUxSHDd27_LMTH_owJIqkF3NOJd9mYQuAv22oNKFYbH8e41pVKb8cT33Y9CgcQ_sy6YDA5PTuIRi67mjKge_nD9rd0IN213Ir9M_EFWqg9e4haWzIdHXQUo0md70kVhPX4UIH_BKJnxEEnFfoFRNMh77bB0N4jkcBEHPl-ghOERv8dOztf4vCnNpzzWvcLD2cqWIm6THy8XGGq9h4hp8aEreRleSMwv9QQAC7mjLwhQ1rBYkpUHlpTjhTLnMwHknl6HH0Z6zzmsgkRKVyfquv94Pd7QbQfZrRka0ss_48pf9p8hAywEn81Q=="
|
||||
}
|
||||
@@ -105,6 +105,7 @@ try
|
||||
});
|
||||
builder.Services.AddOpenApi();
|
||||
|
||||
// TODO: Update to configure with EnvelopeGenerator.DependencyInjection
|
||||
//AddEF Core dbcontext
|
||||
var useDbMigration = Environment.GetEnvironmentVariable("MIGRATION_TEST_MODE") == true.ToString() || config.GetValue<bool>("UseDbMigration");
|
||||
var cnnStrName = useDbMigration ? "DbMigrationTest" : "Default";
|
||||
@@ -185,7 +186,7 @@ try
|
||||
// Envelope generator serives
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
builder.Services
|
||||
.AddEnvelopeGeneratorInfrastructureServices(opt =>
|
||||
.AddEGInfrastructureServices(opt =>
|
||||
{
|
||||
opt.AddDbTriggerParams(config);
|
||||
opt.AddDbContext((provider, options) =>
|
||||
|
||||
@@ -38,10 +38,10 @@ namespace EnvelopeGenerator.Infrastructure
|
||||
/// will be created per HTTP request (or per scope) within the dependency injection container.
|
||||
/// </remarks>
|
||||
[Obsolete("Use IRepository")]
|
||||
public static IServiceCollection AddEnvelopeGeneratorInfrastructureServices(this IServiceCollection services, Action<Config> options)
|
||||
public static IServiceCollection AddEGInfrastructureServices(this IServiceCollection services, Action<EGInfrastructureConfiguration> options)
|
||||
{
|
||||
// configure custom options
|
||||
options(new Config(services));
|
||||
options(new EGInfrastructureConfiguration(services));
|
||||
#if NET
|
||||
services.TryAddScoped<IConfigRepository, ConfigRepository>();
|
||||
services.TryAddScoped<IDocumentReceiverElementRepository, DocumentReceiverElementRepository>();
|
||||
@@ -160,11 +160,11 @@ namespace EnvelopeGenerator.Infrastructure
|
||||
}
|
||||
#endif
|
||||
|
||||
public class Config
|
||||
public class EGInfrastructureConfiguration
|
||||
{
|
||||
private readonly IServiceCollection _services;
|
||||
|
||||
internal Config(IServiceCollection services)
|
||||
internal EGInfrastructureConfiguration(IServiceCollection services)
|
||||
{
|
||||
_services = services;
|
||||
}
|
||||
|
||||
@@ -79,6 +79,10 @@ public abstract class EGDbContextBase : DbContext
|
||||
|
||||
public DbSet<ClientUser> ClientUsers { get; set; }
|
||||
|
||||
public DbSet<ThirdPartyModule> ThirdPartyModules { get; set; }
|
||||
|
||||
public DbSet<EnvelopeReport> EnvelopeReports { get; set; }
|
||||
|
||||
private readonly DbTriggerParams _triggers;
|
||||
|
||||
private readonly ILogger
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Dapper" Version="2.1.66" />
|
||||
<PackageReference Include="DigitalData.Core.Abstraction.Application" Version="1.4.0" />
|
||||
<PackageReference Include="DigitalData.Core.Infrastructure" Version="2.4.5" />
|
||||
<PackageReference Include="DigitalData.Core.Abstraction.Application" Version="1.5.0" />
|
||||
<PackageReference Include="DigitalData.Core.Infrastructure" Version="2.5.0" />
|
||||
<PackageReference Include="QuestPDF" Version="2025.7.1" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -525,7 +525,7 @@ namespace EnvelopeGenerator.Infrastructure.Migrations
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EnvelopeGenerator.Domain.Entities.Config", b =>
|
||||
modelBuilder.Entity("EnvelopeGenerator.Domain.Entities.EGInfrastructureConfiguration", b =>
|
||||
{
|
||||
b.Property<string>("ExportPath")
|
||||
.HasColumnType("nvarchar(256)")
|
||||
|
||||
@@ -522,7 +522,7 @@ namespace EnvelopeGenerator.Infrastructure.Migrations
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EnvelopeGenerator.Domain.Entities.Config", b =>
|
||||
modelBuilder.Entity("EnvelopeGenerator.Domain.Entities.EGInfrastructureConfiguration", b =>
|
||||
{
|
||||
b.Property<string>("ExportPath")
|
||||
.HasColumnType("nvarchar(256)")
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Bogus" Version="35.6.3" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||
<PackageReference Include="DigitalData.Core.Abstraction.Application" Version="1.4.0" />
|
||||
<PackageReference Include="DigitalData.Core.Abstraction.Application" Version="1.5.0" />
|
||||
<PackageReference Include="DigitalData.Core.Abstractions" Version="4.3.0" />
|
||||
<PackageReference Include="DigitalData.Core.API" Version="2.2.1" />
|
||||
<PackageReference Include="DigitalData.Core.Application" Version="3.4.0" />
|
||||
|
||||
@@ -4,7 +4,6 @@ using EnvelopeGenerator.Application.Common.Extensions;
|
||||
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
||||
using EnvelopeGenerator.Application.Common.Notifications.DocSigned;
|
||||
using EnvelopeGenerator.Application.EnvelopeReceivers.Queries;
|
||||
using EnvelopeGenerator.Application.Histories.Queries;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using EnvelopeGenerator.Web.Extensions;
|
||||
using MediatR;
|
||||
@@ -12,6 +11,7 @@ using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Dynamic;
|
||||
|
||||
namespace EnvelopeGenerator.Web.Controllers;
|
||||
|
||||
@@ -58,9 +58,7 @@ public class AnnotationController : ControllerBase
|
||||
|
||||
// Again check if receiver has already signed
|
||||
if (await _mediator.IsSignedAsync(uuid, signature, cancel))
|
||||
return Problem(statusCode: 409);
|
||||
else if (await _mediator.AnyHistoryAsync(uuid, new[] { EnvelopeStatus.EnvelopeRejected, EnvelopeStatus.DocumentRejected }, cancel))
|
||||
return Problem(statusCode: 423);
|
||||
return Problem(statusCode: 403);
|
||||
|
||||
var docSignedNotification = await _mediator
|
||||
.ReadEnvelopeReceiverAsync(uuid, signature, cancel)
|
||||
@@ -73,7 +71,7 @@ public class AnnotationController : ControllerBase
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
||||
[Authorize(Roles = ReceiverRole.FullyAuth)]
|
||||
[HttpPost("reject")]
|
||||
[Obsolete("Use DigitalData.Core.Exceptions and .Middleware")]
|
||||
|
||||
@@ -95,23 +95,6 @@ public class EnvelopeController : ViewControllerBase
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UseAccessCode
|
||||
if (!er.Envelope!.UseAccessCode)
|
||||
{
|
||||
(string? uuid, string? signature) = decoded.ParseEnvelopeReceiverId();
|
||||
var er_secret_res = await _envRcvService.ReadWithSecretByUuidSignatureAsync(uuid: uuid!, signature: signature!);
|
||||
|
||||
if (er_secret_res.IsFailed)
|
||||
{
|
||||
_logger.LogNotice(er_secret_res.Notices);
|
||||
return this.ViewEnvelopeNotFound();
|
||||
}
|
||||
var er_secret = er_secret_res.Data;
|
||||
await HttpContext.SignInEnvelopeAsync(er_secret, ReceiverRole.FullyAuth);
|
||||
return await CreateShowEnvelopeView(er_secret);
|
||||
}
|
||||
#endregion UseAccessCode
|
||||
|
||||
#region Send Access Code
|
||||
bool accessCodeAlreadyRequested = await _historyService.AccessCodeAlreadyRequested(envelopeId: er.Envelope!.Id, userReference: er.Receiver!.EmailAddress);
|
||||
if (!accessCodeAlreadyRequested)
|
||||
@@ -138,7 +121,7 @@ public class EnvelopeController : ViewControllerBase
|
||||
|
||||
[HttpPost("{envelopeReceiverId}")]
|
||||
[Obsolete("Use MediatR")]
|
||||
public async Task<IActionResult> LogInEnvelope([FromRoute] string envelopeReceiverId, [FromForm] Auth auth, CancellationToken cancel)
|
||||
public async Task<IActionResult> LogInEnvelope([FromRoute] string envelopeReceiverId, [FromForm] Auth auth)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -162,15 +145,6 @@ public class EnvelopeController : ViewControllerBase
|
||||
}
|
||||
var er_secret = er_secret_res.Data;
|
||||
|
||||
//check rejection
|
||||
var rejRcvrs = await _historyService.ReadRejectingReceivers(er_secret.Envelope!.Id);
|
||||
if (rejRcvrs.Any())
|
||||
{
|
||||
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
ViewBag.IsExt = !rejRcvrs.Contains(er_secret.Receiver); //external if the current user is not rejected
|
||||
return View("EnvelopeRejected", er_secret);
|
||||
}
|
||||
|
||||
// show envelope if already logged in
|
||||
if (User.IsInRole(ReceiverRole.FullyAuth))
|
||||
return await CreateShowEnvelopeView(er_secret);
|
||||
@@ -216,7 +190,7 @@ public class EnvelopeController : ViewControllerBase
|
||||
return this.ViewInnerServiceError();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async Task<IActionResult> CreateEnvelopeLockedView(EnvelopeReceiverDto er, CancellationToken cancel)
|
||||
{
|
||||
var uuidClaim = User.GetAuthEnvelopeUuid();
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
|
||||
namespace EnvelopeGenerator.Web;
|
||||
|
||||
public class EnvelopeCookieManager : ICookieManager
|
||||
{
|
||||
private readonly IEnumerable<string> _envelopeKeyBasedCookieNames;
|
||||
|
||||
private readonly ChunkingCookieManager _inner = new();
|
||||
|
||||
public EnvelopeCookieManager(params string[] envelopeKeyBasedCookieNames)
|
||||
{
|
||||
_envelopeKeyBasedCookieNames = envelopeKeyBasedCookieNames;
|
||||
}
|
||||
|
||||
private string GetCookieName(HttpContext context, string key)
|
||||
{
|
||||
if (!_envelopeKeyBasedCookieNames.Contains(key))
|
||||
return key;
|
||||
|
||||
var envId = context.GetRouteValue("envelopeReceiverId")?.ToString();
|
||||
|
||||
if (string.IsNullOrEmpty(envId) && context.Request.Query.TryGetValue("envKey", out var envKeyValue))
|
||||
envId = envKeyValue;
|
||||
|
||||
if (string.IsNullOrEmpty(envId))
|
||||
return key;
|
||||
|
||||
return $"{key}-{envId}";
|
||||
}
|
||||
|
||||
public string? GetRequestCookie(HttpContext context, string key)
|
||||
{
|
||||
var cookieName = GetCookieName(context, key);
|
||||
return _inner.GetRequestCookie(context, cookieName);
|
||||
}
|
||||
|
||||
public void AppendResponseCookie(HttpContext context, string key, string? value, CookieOptions options)
|
||||
{
|
||||
var cookieName = GetCookieName(context, key);
|
||||
_inner.AppendResponseCookie(context, cookieName, value, options);
|
||||
}
|
||||
|
||||
public void DeleteCookie(HttpContext context, string key, CookieOptions options)
|
||||
{
|
||||
var cookieName = GetCookieName(context, key);
|
||||
_inner.DeleteCookie(context, cookieName, options);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<PackageId>EnvelopeGenerator.Web</PackageId>
|
||||
@@ -12,9 +12,9 @@
|
||||
<PackageTags>digital data envelope generator web</PackageTags>
|
||||
<Description>EnvelopeGenerator.Web is an ASP.NET MVC application developed to manage signing processes. It uses Entity Framework Core (EF Core) for database operations. The user interface for signing processes is developed with Razor View Engine (.cshtml files) and JavaScript under wwwroot, integrated with PSPDFKit. This integration allows users to view and sign documents seamlessly.</Description>
|
||||
<ApplicationIcon>Assets\icon.ico</ApplicationIcon>
|
||||
<Version>3.8.1</Version>
|
||||
<AssemblyVersion>3.8.1</AssemblyVersion>
|
||||
<FileVersion>3.8.1</FileVersion>
|
||||
<Version>3.5.0</Version>
|
||||
<AssemblyVersion>3.5.0</AssemblyVersion>
|
||||
<FileVersion>3.5.0</FileVersion>
|
||||
<Copyright>Copyright © 2025 Digital Data GmbH. All rights reserved.</Copyright>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -2094,13 +2094,20 @@
|
||||
<None Include="wwwroot\lib\bootstrap-icons\icons\zoom-out.svg" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
||||
<PackageReference Include="BuildBundlerMinifier2022" Version="2.9.9" />
|
||||
<PackageReference Include="DigitalData.Core.API" Version="2.2.1" />
|
||||
<PackageReference Include="DigitalData.Core.Exceptions" Version="1.1.0" />
|
||||
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.1.1" />
|
||||
<PackageReference Include="HtmlSanitizer" Version="8.0.865" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.20" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.15">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.20" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="7.0.20" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.2.5" />
|
||||
@@ -2119,56 +2126,6 @@
|
||||
<PackageReference Include="System.Security.Cryptography.Cng" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
||||
<PackageReference Include="BuildBundlerMinifier2022" Version="2.9.9" />
|
||||
<PackageReference Include="DigitalData.Core.API" Version="2.2.1" />
|
||||
<PackageReference Include="DigitalData.Core.Exceptions" Version="1.1.0" />
|
||||
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.1.1" />
|
||||
<PackageReference Include="HtmlSanitizer" Version="8.0.865" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="7.0.20" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.2.5" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="5.3.0" />
|
||||
<PackageReference Include="Quartz" Version="3.8.0" />
|
||||
<PackageReference Include="Quartz.AspNetCore" Version="3.8.0" />
|
||||
<PackageReference Include="Quartz.Plugins" Version="3.8.0" />
|
||||
<PackageReference Include="Quartz.Serialization.Json" Version="3.8.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.0.1" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="8.0.1" />
|
||||
<PackageReference Include="System.Diagnostics.PerformanceCounter" Version="7.0.0" />
|
||||
<PackageReference Include="System.DirectoryServices" Version="8.0.0" />
|
||||
<PackageReference Include="System.DirectoryServices.AccountManagement" Version="8.0.1" />
|
||||
<PackageReference Include="System.DirectoryServices.Protocols" Version="8.0.1" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="8.0.16" />
|
||||
<PackageReference Include="System.Security.Cryptography.Cng" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
|
||||
<PackageReference Include="BuildBundlerMinifier2022" Version="2.9.9" />
|
||||
<PackageReference Include="DigitalData.Core.API" Version="2.2.1" />
|
||||
<PackageReference Include="DigitalData.Core.Exceptions" Version="1.1.0" />
|
||||
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.1.1" />
|
||||
<PackageReference Include="HtmlSanitizer" Version="8.0.865" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="7.0.20" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.2.5" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="5.3.0" />
|
||||
<PackageReference Include="Quartz" Version="3.8.0" />
|
||||
<PackageReference Include="Quartz.AspNetCore" Version="3.8.0" />
|
||||
<PackageReference Include="Quartz.Plugins" Version="3.8.0" />
|
||||
<PackageReference Include="Quartz.Serialization.Json" Version="3.8.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.0.1" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="9.0.11" />
|
||||
<PackageReference Include="System.Diagnostics.PerformanceCounter" Version="7.0.0" />
|
||||
<PackageReference Include="System.DirectoryServices" Version="9.0.4" />
|
||||
<PackageReference Include="System.DirectoryServices.AccountManagement" Version="9.0.4" />
|
||||
<PackageReference Include="System.DirectoryServices.Protocols" Version="9.0.4" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="9.0.5" />
|
||||
<PackageReference Include="System.Security.Cryptography.Cng" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Application\EnvelopeGenerator.Application.csproj" />
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj" />
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using EnvelopeGenerator.Application.Services;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NLog;
|
||||
using Quartz;
|
||||
@@ -16,8 +15,6 @@ using EnvelopeGenerator.Web.Sanitizers;
|
||||
using EnvelopeGenerator.Web.Models.Annotation;
|
||||
using DigitalData.UserManager.DependencyInjection;
|
||||
using EnvelopeGenerator.Web.Middleware;
|
||||
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
||||
using EnvelopeGenerator.Web;
|
||||
|
||||
var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
|
||||
logger.Info("Logging initialized!");
|
||||
@@ -89,6 +86,7 @@ try
|
||||
builder.Services.AddSwaggerGen();
|
||||
}
|
||||
|
||||
// TODO: Update to configure with EnvelopeGenerator.DependencyInjection
|
||||
//AddEF Core dbcontext
|
||||
var useDbMigration = Environment.GetEnvironmentVariable("MIGRATION_TEST_MODE") == true.ToString() || config.GetValue<bool>("UseDbMigration");
|
||||
var cnnStrName = useDbMigration ? "DbMigrationTest" : "Default";
|
||||
@@ -104,7 +102,7 @@ try
|
||||
|
||||
// Add envelope generator services
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
builder.Services.AddEnvelopeGeneratorInfrastructureServices(
|
||||
builder.Services.AddEGInfrastructureServices(
|
||||
opt =>
|
||||
{
|
||||
opt.AddDbTriggerParams(config);
|
||||
@@ -135,22 +133,41 @@ try
|
||||
options.ConsentCookie.Name = "cookie-consent-settings";
|
||||
});
|
||||
|
||||
var authCookieName = "env_auth";
|
||||
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
|
||||
.AddCookie(options =>
|
||||
{
|
||||
options.Cookie.Name = authCookieName;
|
||||
options.CookieManager = new EnvelopeCookieManager(authCookieName);
|
||||
options.Cookie.HttpOnly = true;
|
||||
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
|
||||
options.Cookie.SameSite = SameSiteMode.Strict;
|
||||
options.Cookie.HttpOnly = true; // Makes the cookie inaccessible to client-side scripts for security
|
||||
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; // Ensures cookies are sent over HTTPS only
|
||||
options.Cookie.SameSite = SameSiteMode.Strict; // Protects against CSRF attacks by restricting how cookies are sent with requests from external sites
|
||||
options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
|
||||
|
||||
options.Events = new CookieAuthenticationEvents
|
||||
{
|
||||
OnRedirectToLogin = context =>
|
||||
{
|
||||
// Dynamically calculate the redirection path, for example:
|
||||
var envelopeReceiverId = context.HttpContext.Request.RouteValues["envelopeReceiverId"];
|
||||
context.RedirectUri = $"/EnvelopeKey/{envelopeReceiverId}";
|
||||
|
||||
context.Response.Redirect(context.RedirectUri);
|
||||
return Task.CompletedTask;
|
||||
},
|
||||
OnRedirectToLogout = context =>
|
||||
{
|
||||
// Apply a similar redirection logic for logout
|
||||
var envelopeReceiverId = context.HttpContext.Request.RouteValues["envelopeReceiverId"];
|
||||
context.RedirectUri = $"/EnvelopeKey/{envelopeReceiverId}";
|
||||
|
||||
context.Response.Redirect(context.RedirectUri);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
builder.Services.AddSingleton(config.GetSection("ContactLink").Get<ContactLink>() ?? new());
|
||||
|
||||
builder.Services.AddCookieBasedLocalizer();
|
||||
|
||||
|
||||
builder.Services.AddSingleton(HtmlEncoder.Default);
|
||||
builder.Services.AddSingleton(UrlEncoder.Default);
|
||||
builder.Services.AddSanitizer<HtmlSanitizer>();
|
||||
@@ -168,15 +185,8 @@ try
|
||||
builder.Services.Configure<Cultures>(config.GetSection("Cultures"));
|
||||
builder.Services.AddSingleton(sp => sp.GetRequiredService<IOptions<Cultures>>().Value);
|
||||
|
||||
// Register mail services
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
builder.Services.AddScoped<IEnvelopeMailService, EnvelopeMailService>();
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
builder.Services.AddDispatcher<EGDbContext>();
|
||||
|
||||
builder.Services.AddMemoryCache();
|
||||
|
||||
builder.ConfigureBySection<CustomImages>();
|
||||
|
||||
builder.ConfigureBySection<AnnotationParams>();
|
||||
@@ -231,7 +241,7 @@ try
|
||||
app.UseAuthorization();
|
||||
|
||||
var cultures = app.Services.GetRequiredService<Cultures>();
|
||||
if (!cultures.Any())
|
||||
if(!cultures.Any())
|
||||
throw new InvalidOperationException(@"Languages section is missing in the appsettings. Please configure like following.
|
||||
Language is both a name of the culture and the name of the resx file such as Resource.de-DE.resx
|
||||
FIClass is the css class (in wwwroot/lib/flag-icons-main) for the flag of country.
|
||||
@@ -246,7 +256,7 @@ try
|
||||
}
|
||||
]");
|
||||
|
||||
if (!config.GetValue<bool>("DisableMultiLanguage"))
|
||||
if(!config.GetValue<bool>("DisableMultiLanguage"))
|
||||
app.UseCookieBasedLocalizer(cultures.Languages.ToArray());
|
||||
|
||||
app.UseCors("SameOriginPolicy");
|
||||
@@ -255,7 +265,7 @@ try
|
||||
app.MapFallbackToController("Error404", "Home");
|
||||
app.Run();
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch(Exception ex)
|
||||
{
|
||||
logger.Error(ex, "Stopped program because of exception");
|
||||
throw;
|
||||
|
||||
@@ -11,10 +11,12 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
|
||||
<ExcludeApp_Data>false</ExcludeApp_Data>
|
||||
<ProjectGuid>5e0e17c0-ff5a-4246-bf87-1add85376a27</ProjectGuid>
|
||||
<DesktopBuildPackageLocation>P:\Install .Net\0 DD - Smart UP\signFLOW\Web\net8\$(Version)\EnvelopeGenerator.Web.zip</DesktopBuildPackageLocation>
|
||||
<DesktopBuildPackageLocation>P:\Install .Net\0 DD - Smart UP\signFLOW\Web\net9\win64\$(Version)\EnvelopeGenerator.Web.zip</DesktopBuildPackageLocation>
|
||||
<PackageAsSingleFile>true</PackageAsSingleFile>
|
||||
<DeployIisAppPath>EnvelopeGenerator</DeployIisAppPath>
|
||||
<_TargetId>IISWebDeployPackage</_TargetId>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<SelfContained>true</SelfContained>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -79,7 +79,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="markdown">@(envelope?.Message)</div>
|
||||
<h6>@($"{@envelope?.Message}")</h6>
|
||||
}
|
||||
<p>
|
||||
<small class="text-body-secondary">
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.min.js"></script>
|
||||
<script src="~/lib/sweetalert2/sweetalert2.min.js"></script>
|
||||
<script src="~/lib/alertifyjs/alertify.min.js"></script>
|
||||
<script src="~/lib/marked/marked.umd.min.js"></script>
|
||||
<script src="~/js/lazy.min.js" asp-append-version="true"></script>
|
||||
<script src="~/js/ui.min.js" asp-append-version="true"></script>
|
||||
<script src="~/js/annotation.js" asp-append-version="true"></script>
|
||||
@@ -96,6 +95,5 @@
|
||||
</div>
|
||||
<a href="/privacy-policy.@(_localizer.Culture()).html" target="_blank">@_localizer.Privacy()</a>
|
||||
</footer>
|
||||
<script src="~/js/markdown.min.js" asp-append-version="true"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -41,12 +41,6 @@
|
||||
"wwwroot/js/util.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"outputFileName": "wwwroot/js/markdown.min.js",
|
||||
"inputFiles": [
|
||||
"wwwroot/js/markdown.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"outputFileName": "wwwroot/css/error-space.min.css",
|
||||
"inputFiles": [
|
||||
|
||||
@@ -255,7 +255,7 @@ class App {
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
if (res.status === 409) {
|
||||
if (res.status === 403) {
|
||||
Swal.fire({
|
||||
title: 'Warnung',
|
||||
text: 'Umschlag ist nicht mehr verfügbar.',
|
||||
@@ -263,17 +263,6 @@ class App {
|
||||
})
|
||||
return false
|
||||
}
|
||||
else if (res.status === 423) {
|
||||
Swal.fire({
|
||||
title: 'Info',
|
||||
text: 'Dokument wurde von einem Empfänger abgelehnt. Sie werden weitergeleitet...',
|
||||
icon: 'info',
|
||||
timer: 2000,
|
||||
showConfirmButton: false
|
||||
}).then(() => {
|
||||
location.reload();
|
||||
});
|
||||
}
|
||||
else {
|
||||
throw new Error()
|
||||
}
|
||||
|
||||
2
EnvelopeGenerator.Web/wwwroot/js/app.min.js
vendored
2
EnvelopeGenerator.Web/wwwroot/js/app.min.js
vendored
@@ -1,3 +1,3 @@
|
||||
class App{constructor(n,t,i,r,u,f){this.container=f??`#${this.constructor.name.toLowerCase()}`;this.envelopeKey=n;this.pdfKit=null;this.currentDocument=t.envelope.documents[0];this.currentReceiver=t.receiver;this.signatureCount=t.envelope.documents[0].elements.length;this.envelopeReceiver=t;this.documentBytes=i;this.licenseKey=r;this.locale=u}async init(){this.pdfKit=await loadPSPDFKit(this.documentBytes,this.container,this.licenseKey,this.locale);addToolbarItems(this.pdfKit,this.handleClick.bind(this));this.pdfKit.addEventListener("annotations.load",this.handleAnnotationsLoad.bind(this));this.pdfKit.addEventListener("annotations.change",this.handleAnnotationsChange.bind(this));this.pdfKit.addEventListener("annotations.create",this.handleAnnotationsCreate.bind(this));this.pdfKit.addEventListener("annotations.willChange",()=>{Comp.ActPanel.Toggle()});try{let n=await createAnnotations(this.currentDocument,this.envelopeReceiver.envelopeId,this.envelopeReceiver.receiverId);await this.pdfKit.create(n)}catch(n){console.error("Error loading annotations:",n)}[...document.getElementsByClassName("btn_refresh")].forEach(n=>n.addEventListener("click",()=>this.handleClick("RESET")));[...document.getElementsByClassName("btn_complete")].forEach(n=>n.addEventListener("click",()=>this.handleClick("FINISH")));[...document.getElementsByClassName("btn_reject")].forEach(n=>n.addEventListener("click",()=>this.handleClick("REJECT")))}handleAnnotationsLoad(n){n.toJS()}handleAnnotationsChange(){}async handleAnnotationsCreate(n){const t=n.toJS()[0],i=!!t.formFieldName,r=!!t.isSignature;if(i===!1&&r===!0){const r=t.boundingBox.left-20,u=t.boundingBox.top-20,n=150,i=75,f=new Date,e=await createAnnotationFrameBlob(this.envelopeReceiver.name,this.currentReceiver.signature,f,n,i),o=await fetch(e),s=await o.blob(),h=await this.pdfKit.createAttachment(s),c=createImageAnnotation(new PSPDFKit.Geometry.Rect({left:r,top:u,width:n,height:i}),t.pageIndex,h,generateId(this.envelopeReceiver.envelopeId,this.envelopeReceiver.receiverId,this.fakeElementId--,"signed"));this.pdfKit.create(c)}}async handleClick(n){let t=!1;switch(n){case"RESET":t=await this.handleReset(null);Comp.SignatureProgress.SignedCount=0;t.isConfirmed&&Swal.fire({title:"Erfolg",text:"Dokument wurde zurückgesetzt",icon:"info"});break;case"FINISH":t=await this.handleFinish(null);t==!0&&(window.location.href=`/Envelope/${this.envelopeKey}`);break;case"REJECT":Swal.fire({title:localized.rejection,html:`<div class="text-start fs-6 p-0 m-0">${localized.rejectionReasonQ}</div>`,icon:"question",input:"text",inputAttributes:{autocapitalize:"off"},showCancelButton:!0,confirmButtonColor:"#3085d6",cancelButtonColor:"#d33",confirmButtonText:localized.complete,cancelButtonText:localized.back,showLoaderOnConfirm:!0,preConfirm:async n=>{try{return await rejectEnvelope(n)}catch(t){Swal.showValidationMessage(`
|
||||
Request failed: ${t}
|
||||
`)}},allowOutsideClick:()=>!Swal.isLoading()}).then(n=>{if(n.isConfirmed){const t=n.value;t.ok?reload():Swal.showValidationMessage(`Request failed: ${t.message}`)}});break;case"COPY_URL":const n=window.location.href.replace(/\/readonly/gi,"");navigator.clipboard.writeText(n).then(function(){bsNotify("Kopiert",{alert_type:"success",delay:4,icon_name:"check_circle"})}).catch(function(){bsNotify("Unerwarteter Fehler",{alert_type:"danger",delay:4,icon_name:"error"})});break;case"SHARE":Comp.ShareBackdrop.show();break;case"LOGOUT":await logout()}}async handleFinish(){const n=await this.pdfKit.exportInstantJSON(),t=n.formFieldValues,r=t.filter(n=>isFieldRequired(n)),u=r.some(n=>n.value===undefined||n.value===null||n.value==="");if(u)return Swal.fire({title:"Warnung",text:"Bitte füllen Sie alle Standortinformationen vollständig aus!",icon:"warning"}),!1;const f=new RegExp("^[a-zA-Z\\u0080-\\u024F]+(?:([\\ \\-\\']|(\\.\\ ))[a-zA-Z\\u0080-\\u024F]+)*$"),e=t.filter(n=>isCityField(n));for(var i of e)if(!IS_MOBILE_DEVICE&&!f.test(i.value))return Swal.fire({title:"Warnung",text:`Bitte überprüfen Sie die eingegebene Ortsangabe "${i.value}" auf korrekte Formatierung. Beispiele für richtige Formate sind: München, Île-de-France, Sauðárkrókur, San Francisco, St. Catharines usw.`,icon:"warning"}),!1;const o=await this.validateAnnotations(this.signatureCount);return o===!1?(Swal.fire({title:"Warnung",text:"Es wurden nicht alle Signaturfelder ausgefüllt!",icon:"warning"}),!1):Swal.fire({title:localized.confirmation,html:`<div class="text-start fs-6 p-0 m-0">${localized.sigAgree}</div>`,icon:"question",showCancelButton:!0,confirmButtonColor:"#3085d6",cancelButtonColor:"#d33",confirmButtonText:localized.finalize,cancelButtonText:localized.back}).then(async t=>{if(t.isConfirmed){try{await this.pdfKit.save()}catch(i){return Swal.fire({title:"Fehler",text:"Umschlag konnte nicht signiert werden!",icon:"error"}),!1}try{const t=await signEnvelope({instant:n,structured:mapSignature(n)});if(t.ok)return!0;if(t.status===409)return Swal.fire({title:"Warnung",text:"Umschlag ist nicht mehr verfügbar.",icon:"warning"}),!1;if(t.status===423)Swal.fire({title:"Info",text:"Dokument wurde von einem Empfänger abgelehnt. Sie werden weitergeleitet...",icon:"info",timer:2e3,showConfirmButton:!1}).then(()=>{location.reload()});else throw new Error;}catch(i){return Swal.fire({title:"Fehler",text:"Umschlag konnte nicht signiert werden!",icon:"error"}),!1}}else return!1})}async validateAnnotations(n){const t=await getAnnotations(this.pdfKit),i=t.map(n=>n.toJS()).filter(n=>n.isSignature);return n<=i.length}async handleReset(){const n=Swal.fire({title:"Sind sie sicher?",text:"Wollen Sie das Dokument und alle erstellten Signaturen zurücksetzen?",icon:"question",showCancelButton:!0});if(n.isConfirmed){const n=await deleteAnnotations(this.pdfKit)}return n}fakeElementId=0;}
|
||||
`)}},allowOutsideClick:()=>!Swal.isLoading()}).then(n=>{if(n.isConfirmed){const t=n.value;t.ok?reload():Swal.showValidationMessage(`Request failed: ${t.message}`)}});break;case"COPY_URL":const n=window.location.href.replace(/\/readonly/gi,"");navigator.clipboard.writeText(n).then(function(){bsNotify("Kopiert",{alert_type:"success",delay:4,icon_name:"check_circle"})}).catch(function(){bsNotify("Unerwarteter Fehler",{alert_type:"danger",delay:4,icon_name:"error"})});break;case"SHARE":Comp.ShareBackdrop.show();break;case"LOGOUT":await logout()}}async handleFinish(){const n=await this.pdfKit.exportInstantJSON(),t=n.formFieldValues,r=t.filter(n=>isFieldRequired(n)),u=r.some(n=>n.value===undefined||n.value===null||n.value==="");if(u)return Swal.fire({title:"Warnung",text:"Bitte füllen Sie alle Standortinformationen vollständig aus!",icon:"warning"}),!1;const f=new RegExp("^[a-zA-Z\\u0080-\\u024F]+(?:([\\ \\-\\']|(\\.\\ ))[a-zA-Z\\u0080-\\u024F]+)*$"),e=t.filter(n=>isCityField(n));for(var i of e)if(!IS_MOBILE_DEVICE&&!f.test(i.value))return Swal.fire({title:"Warnung",text:`Bitte überprüfen Sie die eingegebene Ortsangabe "${i.value}" auf korrekte Formatierung. Beispiele für richtige Formate sind: München, Île-de-France, Sauðárkrókur, San Francisco, St. Catharines usw.`,icon:"warning"}),!1;const o=await this.validateAnnotations(this.signatureCount);return o===!1?(Swal.fire({title:"Warnung",text:"Es wurden nicht alle Signaturfelder ausgefüllt!",icon:"warning"}),!1):Swal.fire({title:localized.confirmation,html:`<div class="text-start fs-6 p-0 m-0">${localized.sigAgree}</div>`,icon:"question",showCancelButton:!0,confirmButtonColor:"#3085d6",cancelButtonColor:"#d33",confirmButtonText:localized.finalize,cancelButtonText:localized.back}).then(async t=>{if(t.isConfirmed){try{await this.pdfKit.save()}catch(i){return Swal.fire({title:"Fehler",text:"Umschlag konnte nicht signiert werden!",icon:"error"}),!1}try{const t=await signEnvelope({instant:n,structured:mapSignature(n)});if(t.ok)return!0;if(t.status===403)return Swal.fire({title:"Warnung",text:"Umschlag ist nicht mehr verfügbar.",icon:"warning"}),!1;throw new Error;}catch(i){return Swal.fire({title:"Fehler",text:"Umschlag konnte nicht signiert werden!",icon:"error"}),!1}}else return!1})}async validateAnnotations(n){const t=await getAnnotations(this.pdfKit),i=t.map(n=>n.toJS()).filter(n=>n.isSignature);return n<=i.length}async handleReset(){const n=Swal.fire({title:"Sind sie sicher?",text:"Wollen Sie das Dokument und alle erstellten Signaturen zurücksetzen?",icon:"question",showCancelButton:!0});if(n.isConfirmed){const n=await deleteAnnotations(this.pdfKit)}return n}fakeElementId=0;}
|
||||
@@ -1,111 +1,106 @@
|
||||
//#region parameters
|
||||
const env = Object.freeze({
|
||||
__lazyXsrfToken: new Lazy(() => document.getElementsByName('__RequestVerificationToken')[0].value),
|
||||
get xsrfToken() {
|
||||
return this.__lazyXsrfToken.value;
|
||||
}
|
||||
__lazyXsrfToken: new Lazy(() => document.getElementsByName('__RequestVerificationToken')[0].value),
|
||||
get xsrfToken() {
|
||||
return this.__lazyXsrfToken.value;
|
||||
}
|
||||
})
|
||||
|
||||
const url = Object.freeze({
|
||||
reject: `/api/annotation/reject`,
|
||||
share: `/api/readonly`
|
||||
reject: `/api/annotation/reject`,
|
||||
share: `/api/readonly`
|
||||
});
|
||||
//#endregion
|
||||
|
||||
//#region request helper methods
|
||||
function sendRequest(method, url, body = undefined) {
|
||||
const urlObj = new URL(url, window.location.origin);
|
||||
if (!urlObj.searchParams.has("envKey")) {
|
||||
urlObj.searchParams.set("envKey", ENV_KEY);
|
||||
const options = {
|
||||
credentials: 'include',
|
||||
method: method,
|
||||
headers: {
|
||||
'X-XSRF-TOKEN': env.xsrfToken
|
||||
}
|
||||
}
|
||||
|
||||
const options = {
|
||||
credentials: 'include',
|
||||
method: method,
|
||||
headers: {
|
||||
'X-XSRF-TOKEN': env.xsrfToken
|
||||
}
|
||||
}
|
||||
if (body !== undefined) {
|
||||
options.body = JSON.stringify(body);
|
||||
options.headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
|
||||
if (body !== undefined) {
|
||||
options.body = JSON.stringify(body);
|
||||
options.headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
|
||||
return fetch(urlObj, options);
|
||||
return fetch(url, options);
|
||||
}
|
||||
|
||||
function getRequest(url) {
|
||||
return sendRequest('GET', url);
|
||||
return sendRequest('GET', url);
|
||||
}
|
||||
|
||||
function getJson(url) {
|
||||
return sendRequest('GET', url).then(res => {
|
||||
if (res.ok)
|
||||
return res.json();
|
||||
throw new Error(`Request failed with status ${res.status}`);
|
||||
});
|
||||
return sendRequest('GET', url).then(res => {
|
||||
if (res.ok)
|
||||
return res.json();
|
||||
throw new Error(`Request failed with status ${res.status}`);
|
||||
});
|
||||
}
|
||||
|
||||
function postRequest(url, body = undefined) {
|
||||
return sendRequest('POST', url, body);
|
||||
return sendRequest('POST', url, body);
|
||||
}
|
||||
|
||||
function reload() {
|
||||
window.location.reload();
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
function redirect(url) {
|
||||
window.location.href = url;
|
||||
window.location.href = url;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region envelope
|
||||
function signEnvelope(annotations) {
|
||||
return postRequest(`/api/annotation`, annotations)
|
||||
return postRequest(`/api/annotation`, annotations)
|
||||
}
|
||||
|
||||
async function getAnnotationParams(leftInInch = 0, topInInch = 0, inchToPointFactor = 72) {
|
||||
const annotParams = await getJson("/api/Config/Annotations");
|
||||
const annotParams = await getJson("/api/Config/Annotations");
|
||||
|
||||
for (var key in annotParams) {
|
||||
var annot = annotParams[key];
|
||||
annot.width *= inchToPointFactor;
|
||||
annot.height *= inchToPointFactor;
|
||||
annot.left += leftInInch - 0.7;
|
||||
annot.left *= inchToPointFactor;
|
||||
annot.top += topInInch - 0.5;
|
||||
annot.top *= inchToPointFactor;
|
||||
}
|
||||
for (var key in annotParams) {
|
||||
var annot = annotParams[key];
|
||||
annot.width *= inchToPointFactor;
|
||||
annot.height *= inchToPointFactor;
|
||||
annot.left += leftInInch - 0.7;
|
||||
annot.left *= inchToPointFactor;
|
||||
annot.top += topInInch - 0.5;
|
||||
annot.top *= inchToPointFactor;
|
||||
}
|
||||
|
||||
return annotParams;
|
||||
return annotParams;
|
||||
}
|
||||
|
||||
function rejectEnvelope(reason) {
|
||||
return postRequest(url.reject, reason);
|
||||
return postRequest(url.reject, reason);
|
||||
}
|
||||
|
||||
function shareEnvelope(receiverMail, dateValid) {
|
||||
return postRequest(url.share, { receiverMail: receiverMail, dateValid: dateValid });
|
||||
return postRequest(url.share, { receiverMail: receiverMail, dateValid: dateValid });
|
||||
}
|
||||
//#endregion
|
||||
|
||||
async function setLanguage(language) {
|
||||
const hasLang = await getJson('/api/localization/lang')
|
||||
.then(langs => langs.includes(language));
|
||||
const hasLang = await getJson('/api/localization/lang')
|
||||
.then(langs => langs.includes(language));
|
||||
|
||||
if (hasLang)
|
||||
postRequest(`/api/localization/lang/${language}`)
|
||||
.then(response => {
|
||||
if (response.redirected)
|
||||
redirect(response.url);
|
||||
});
|
||||
if (hasLang)
|
||||
postRequest(`/api/localization/lang/${language}`)
|
||||
.then(response => {
|
||||
if (response.redirected)
|
||||
redirect(response.url);
|
||||
});
|
||||
}
|
||||
|
||||
function logout() {
|
||||
return postRequest(`/auth/logout`)
|
||||
.then(res => {
|
||||
if (res.ok)
|
||||
window.location.href = "/";
|
||||
});
|
||||
return postRequest(`/auth/logout`)
|
||||
.then(res => {
|
||||
if (res.ok)
|
||||
window.location.href = "/";
|
||||
});
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
function sendRequest(n,t,i=undefined){const r=new URL(t,window.location.origin);r.searchParams.has("envKey")||r.searchParams.set("envKey",ENV_KEY);const u={credentials:"include",method:n,headers:{"X-XSRF-TOKEN":env.xsrfToken}};return i!==undefined&&(u.body=JSON.stringify(i),u.headers["Content-Type"]="application/json"),fetch(r,u)}function getRequest(n){return sendRequest("GET",n)}function getJson(n){return sendRequest("GET",n).then(n=>{if(n.ok)return n.json();throw new Error(`Request failed with status ${n.status}`);})}function postRequest(n,t=undefined){return sendRequest("POST",n,t)}function reload(){window.location.reload()}function redirect(n){window.location.href=n}function signEnvelope(n){return postRequest(`/api/annotation`,n)}async function getAnnotationParams(n=0,t=0,i=72){var f,r;const u=await getJson("/api/Config/Annotations");for(f in u)r=u[f],r.width*=i,r.height*=i,r.left+=n-.7,r.left*=i,r.top+=t-.5,r.top*=i;return u}function rejectEnvelope(n){return postRequest(url.reject,n)}function shareEnvelope(n,t){return postRequest(url.share,{receiverMail:n,dateValid:t})}async function setLanguage(n){const t=await getJson("/api/localization/lang").then(t=>t.includes(n));t&&postRequest(`/api/localization/lang/${n}`).then(n=>{n.redirected&&redirect(n.url)})}function logout(){return postRequest(`/auth/logout`).then(n=>{n.ok&&(window.location.href="/")})}const env=Object.freeze({__lazyXsrfToken:new Lazy(()=>document.getElementsByName("__RequestVerificationToken")[0].value),get xsrfToken(){return this.__lazyXsrfToken.value}}),url=Object.freeze({reject:`/api/annotation/reject`,share:`/api/readonly`});
|
||||
function sendRequest(n,t,i=undefined){const r={credentials:"include",method:n,headers:{"X-XSRF-TOKEN":env.xsrfToken}};return i!==undefined&&(r.body=JSON.stringify(i),r.headers["Content-Type"]="application/json"),fetch(t,r)}function getRequest(n){return sendRequest("GET",n)}function getJson(n){return sendRequest("GET",n).then(n=>{if(n.ok)return n.json();throw new Error(`Request failed with status ${n.status}`);})}function postRequest(n,t=undefined){return sendRequest("POST",n,t)}function reload(){window.location.reload()}function redirect(n){window.location.href=n}function signEnvelope(n){return postRequest(`/api/annotation`,n)}async function getAnnotationParams(n=0,t=0,i=72){var f,r;const u=await getJson("/api/Config/Annotations");for(f in u)r=u[f],r.width*=i,r.height*=i,r.left+=n-.7,r.left*=i,r.top+=t-.5,r.top*=i;return u}function rejectEnvelope(n){return postRequest(url.reject,n)}function shareEnvelope(n,t){return postRequest(url.share,{receiverMail:n,dateValid:t})}async function setLanguage(n){const t=await getJson("/api/localization/lang").then(t=>t.includes(n));t&&postRequest(`/api/localization/lang/${n}`).then(n=>{n.redirected&&redirect(n.url)})}function logout(){return postRequest(`/auth/logout`).then(n=>{n.ok&&(window.location.href="/")})}const env=Object.freeze({__lazyXsrfToken:new Lazy(()=>document.getElementsByName("__RequestVerificationToken")[0].value),get xsrfToken(){return this.__lazyXsrfToken.value}}),url=Object.freeze({reject:`/api/annotation/reject`,share:`/api/readonly`});
|
||||
@@ -1,11 +0,0 @@
|
||||
marked.use({
|
||||
async: true,
|
||||
breaks: true,
|
||||
gfm: true,
|
||||
});
|
||||
|
||||
(async () => {
|
||||
for (const el of document.querySelectorAll('.markdown')) {
|
||||
el.innerHTML = await marked.parse(el.textContent.replace(/(\t| )/g, " "));
|
||||
}
|
||||
})();
|
||||
@@ -1 +0,0 @@
|
||||
marked.use({"async":!0,breaks:!0,gfm:!0});(async()=>{for(const n of document.querySelectorAll(".markdown"))n.innerHTML=await marked.parse(n.textContent.replace(/(\t| )/g," "))})();
|
||||
File diff suppressed because one or more lines are too long
@@ -4,14 +4,14 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Datenschutzinformation für das Fernsignatursystem: signFLOW</title>
|
||||
<title>Datenschutzinformation für das Fernsignatursystem signFLOW</title>
|
||||
<link rel="stylesheet" href="css/privacy-policy.min.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<h1>Datenschutzinformation für das Fernsignatursystem signFLOW</h1>
|
||||
<p><strong>Stand:</strong> 18.11.2025</p>
|
||||
<p><strong>Stand:</strong> 19.09.2024</p>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
@@ -55,7 +55,7 @@
|
||||
<h2>3. Datenerhebung</h2>
|
||||
<h3>3.1 Die folgenden Kategorien personenbezogener Daten werden verarbeitet</h3>
|
||||
<ul>
|
||||
<li>Namen: Benutzername, Vor- und Zunamen sowie Ihre digitale Unterschrift</li>
|
||||
<li>Namen: Vor- und Zunamen sowie Ihre digitale Unterschrift</li>
|
||||
<li>Kontaktdaten: Telefonnummer, Mobilfunknummer und E-Mail-Adresse</li>
|
||||
<li>Technische Daten: IP-Adresse, Zeitpunkt des Zugriffs oder Zugriffsversuchs</li>
|
||||
</ul>
|
||||
@@ -162,6 +162,138 @@
|
||||
<a href="https://www.bfdi.bund.de/DE/Service/Anschriften/Laender/Laender-node.html">Laender-node.html</a>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>6. Hinweisgebersystem</h2>
|
||||
<p>
|
||||
Die Einhaltung gesetzlicher Vorschriften und interner Richtlinien, einschließlich unseres Verhaltenskodexes
|
||||
sowie des Verhaltenskodexes für Geschäftspartner, hat für uns (die verarbeitende Stelle) oberste Priorität.
|
||||
Dies gilt sowohl für unseren eigenen Geschäftsbereich als auch für unsere Lieferketten.
|
||||
</p>
|
||||
<p>
|
||||
Es ist uns wichtig, Risiken frühzeitig zu identifizieren und Verstöße zu vermeiden. Wir möchten rechtzeitig
|
||||
geeignete Maßnahmen ergreifen, um mögliche Schäden für Betroffene, Kunden, Mitarbeiter, Geschäftspartner und
|
||||
unsere Unternehmensgruppe zu verhindern.
|
||||
</p>
|
||||
<p>
|
||||
Aus diesem Grund haben wir ein unabhängiges, neutrales und vertrauliches Hinweisgebersystem eingerichtet,
|
||||
das es internen und externen Hinweisgebenden ermöglicht, auch anonym Meldungen abzugeben. Durch unser
|
||||
transparentes Beschwerdeverfahren bieten wir insbesondere den Betroffenen, den Hinweisgebenden und den
|
||||
Mitarbeitenden, die an der Aufklärung der gemeldeten Vorfälle mitwirken, den größtmöglichen Schutz.
|
||||
</p>
|
||||
<p>
|
||||
Im Rahmen dieses Verfahrens können alle tatsächlichen und vermeintlichen Verstöße gegen gesetzliche
|
||||
Vorgaben, unseren Verhaltenskodex sowie den Verhaltenskodex für Geschäftspartner gemeldet werden. Auch
|
||||
menschenrechtliche oder umweltbezogene Risiken sowie Pflichtverletzungen entlang der gesamten Lieferkette
|
||||
unserer Konzernunternehmen und in unserem eigenen Geschäftsbereich können Gegenstand einer Meldung sein.
|
||||
</p>
|
||||
<p>
|
||||
Einheitliche und zügige Prozesse sowie eine vertrauliche und professionelle Bearbeitung der Hinweise durch
|
||||
interne Experten bilden die Grundlage dieses fairen Verfahrens. Benachteiligungen oder Bestrafungen von
|
||||
Hinweisgebenden sowie von Personen, die mit der Bearbeitung von Beschwerden und Hinweisen betraut sind,
|
||||
werden nicht toleriert.
|
||||
</p>
|
||||
|
||||
<h3>6.1 Zweck und Rechtsgrundlage der Datenverarbeitung</h3>
|
||||
<p>
|
||||
Der Zweck der Verarbeitung personenbezogener Daten besteht in der Verwaltung des Hinweisgebersystems, das
|
||||
auch die Aufdeckung schwerwiegender Verstöße oder potenzieller Verstöße gegen geltendes Recht sowie anderer
|
||||
ernsthafter Angelegenheiten umfasst. Die Verarbeitung dieser Daten ist notwendig, um rechtlichen
|
||||
Verpflichtungen nachzukommen, die uns auferlegt sind, gemäß Art. 6 Abs. 1 S. 1 lit. c) DSGVO. Dies
|
||||
bezieht
|
||||
sich auf das Gesetz, das den Schutz von Hinweisgebern verbessert (Hinweisgeberschutzgesetz - HinSchG).
|
||||
</p>
|
||||
<p>
|
||||
Zudem dient die Verarbeitung dem berechtigten Interesse, schwerwiegende Verstöße oder mögliche Verstöße
|
||||
gegen geltendes Recht sowie andere ernsthafte Angelegenheiten aufzudecken, gemäß Art. 6 Abs. 1 S. 1 lit.
|
||||
f)
|
||||
DSGVO.
|
||||
</p>
|
||||
<p>
|
||||
Im Hinblick auf die Verarbeitung besonderer Kategorien personenbezogener Daten ist diese auf Grundlage des
|
||||
Hinweisgeberschutzgesetzes aus Gründen eines erheblichen öffentlichen Interesses erforderlich, gemäß Art. 9
|
||||
Abs. 2 lit. g) DSGVO. Die Verarbeitung dieser besonderen Daten erfolgt gemäß Art. 9 Abs. 2 lit. f)
|
||||
DSGVO in
|
||||
Verbindung mit Art. 6 Abs. 1 S. 1 lit. f) DSGVO, um Rechtsansprüche festzustellen, auszuüben oder zu
|
||||
verteidigen.
|
||||
</p>
|
||||
<p>
|
||||
Betroffene Personen sind diejenigen, über die eine Meldung gemacht wird. Dies können Mitarbeiter,
|
||||
Vertragspartner oder andere Personen sein, die in beruflicher Verbindung zu der verarbeitenden Stelle
|
||||
stehen. Darüber hinaus verarbeiten wir personenbezogene Daten der hinweisgebenden Person, wenn diese ihre
|
||||
Kontaktinformationen oder andere identifizierende Informationen übermittelt. Hinweisgebende Personen sollten
|
||||
sich daher bewusst sein, dass wir im Rahmen der Bearbeitung des gemeldeten Falls personenbezogene Daten über
|
||||
sie verarbeiten können.
|
||||
</p>
|
||||
|
||||
<h3>6.2 Kategorien personenbezogener Daten</h3>
|
||||
<p>
|
||||
Die Meldung kann anonym erfolgen, wodurch keine personenbezogenen Daten der meldenden Person verarbeitet
|
||||
werden. Die Art der personenbezogenen Daten, die verarbeitet werden, hängt von den übermittelten
|
||||
Informationen ab. Wenn die meldende Person personenbezogene Daten über eine andere Person, einschließlich
|
||||
der gemeldeten Person oder Personen, angibt, werden auch diese Daten verarbeitet. Folgende Kategorien von
|
||||
personenbezogenen Daten können verarbeitet werden:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Allgemeine personenbezogene Daten (z.B.: Vorname, Nachname, Adresse, E-Mail-Adresse, Telefonnummer,
|
||||
usw.)</li>
|
||||
<li>Personenbezogene Daten zu strafrechtlichen Verurteilungen oder Verdachtsmomenten</li>
|
||||
<li>Besondere Kategorien personenbezogener Daten (Informationen über rassische oder ethnische Herkunft,
|
||||
politische Meinungen, religiöse oder philosophische Überzeugungen, Gewerkschaftszugehörigkeit,
|
||||
Gesundheitsdaten sowie Informationen über das Sexualleben oder die sexuelle Orientierung einer Person)
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
Wir bitten die meldende Person, ausschließlich Informationen zu übermitteln, die für den jeweiligen Fall von
|
||||
Bedeutung sind, und insbesondere keine sensiblen Informationen zu melden, es sei denn, diese sind für die
|
||||
Bearbeitung des gemeldeten Falls von zentraler Relevanz.
|
||||
</p>
|
||||
|
||||
<h3>6.3 Verpflichtung zur Bereitstellung personenbezogener Daten</h3>
|
||||
<p>
|
||||
Es ist nicht erforderlich, die im Abschnitt 6.2 genannten personenbezogenen Daten bereitzustellen, da auch
|
||||
eine anonyme Meldung möglich ist. Bitte beachte jedoch, dass wir möglicherweise nicht in der Lage sind, die
|
||||
Meldung zu bearbeiten, wenn keine personenbezogenen Daten angegeben werden.
|
||||
</p>
|
||||
|
||||
<h3>6.4 Empfänger personenbezogener Daten</h3>
|
||||
<p>Die Meldungen werden bei der verarbeitenden Stelle im System als Vorgänge erfasst. Nach einer Bewertung
|
||||
werden diese Vorgänge intern an die zuständigen Fachabteilungen weitergeleitet, und gegebenenfalls werden
|
||||
Folgemaßnahmen eingeleitet. Sollte eine Meldung eine der Konzerngesellschaften der verarbeitenden Stelle
|
||||
betreffen, werden die relevanten Vorgänge an die zuständigen Personen der jeweiligen Gesellschaft
|
||||
weitergegeben, die dann intern eine Bewertung vornehmen und gegebenenfalls Maßnahmen ergreifen. Bei der
|
||||
Weitergabe personenbezogener Daten wird der Grundsatz der Datenminimierung beachtet, was bedeutet, dass nur
|
||||
die unbedingt notwendigen Daten zur Bearbeitung der Meldung weitergegeben werden.</p>
|
||||
<p>Personenbezogene Daten der hinweisgebenden Person werden an Behörden weitergeleitet, wenn dies erforderlich
|
||||
ist, um schwerwiegende Verstöße oder Angelegenheiten zu behandeln oder das Recht auf Verteidigung der
|
||||
betroffenen Personen zu sichern. In anderen Fällen erfolgt die Weitergabe personenbezogener Daten der
|
||||
hinweisgebenden Person nur mit deren Zustimmung. Daten über andere Personen als die hinweisgebende Person
|
||||
werden nur im Rahmen der Nachverfolgung eines gemeldeten Falls oder zur Bearbeitung schwerwiegender Verstöße
|
||||
oder Angelegenheiten weitergegeben.</p>
|
||||
<p>Die Meldeplattform wird von dem Auftragsverarbeiter WhistleB Whistleblowing Centre AB mit Sitz in Stockholm,
|
||||
Schweden, bereitgestellt. Weitere Informationen zu WhistleB und den entsprechenden Nutzungsbedingungen sind
|
||||
dort einsehbar.
|
||||
<a
|
||||
href="https://report.whistleb.com/content/documents/whistleb_terms_of_use.pdf">whistleb_terms_of_use.pdf</a>
|
||||
</p>
|
||||
|
||||
<h3>6.5 Speicherdauer</h3>
|
||||
<p>Personenbezogene Daten, die sich als nicht relevant für die Bearbeitung eines gemeldeten Falls herausstellen,
|
||||
sowie Meldungen, die wir als unbegründet ansehen, werden umgehend als "nicht relevant" eingestuft. In diesem
|
||||
Fall wird der Personenbezug entfernt, es sei denn, es handelt sich bereits um eine anonyme Meldung. Um die
|
||||
gesetzlich vorgeschriebene Dokumentationspflicht und die Löschfristen gemäß § 11 Abs. 1 und Abs. 5 HinSchG
|
||||
zu erfüllen, wird die Meldung zunächst ohne Personenbezug archiviert, jedoch noch nicht gelöscht.
|
||||
Archivierte Fälle dienen ausschließlich der Erfüllung dieser Dokumentationspflichten und können danach nicht
|
||||
mehr zur Bearbeitung herangezogen werden.</p>
|
||||
<p>Die Meldungen und personenbezogenen Daten, die im Zuge der Bearbeitung einer Meldung erfasst werden, bilden
|
||||
die Grundlage für die weitere Bearbeitung und werden so schnell wie möglich anonymisiert. Sollte es
|
||||
notwendig sein, Folgemaßnahmen gemäß §§ 3 Abs. 8 und 18 HinSchG zu ergreifen, kann es jedoch erforderlich
|
||||
sein, von der Anonymisierung abzuweichen, sei es aufgrund behördlicher Anordnungen oder zur Wahrung von
|
||||
Rechtsansprüchen. In solchen Fällen wird in der Regel eine Pseudonymisierung angestrebt, es sei denn, es
|
||||
gibt andere Vorgaben, wie etwa eine richterliche Anordnung. Die Dokumentation wird drei Jahre nach Abschluss
|
||||
des Verfahrens gelöscht. Sie kann jedoch länger aufbewahrt werden, um den Anforderungen dieses Gesetzes oder
|
||||
anderer Rechtsvorschriften gerecht zu werden, solange dies notwendig und angemessen ist.</p>
|
||||
</section>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -10,8 +10,8 @@
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<h1>Data Protection Information for the Remote Signature System: signFLOW</h1>
|
||||
<p><strong>As of:</strong> 18.11.2025</p>
|
||||
<h1>Data Protection Information for the Remote Signature System signFLOW</h1>
|
||||
<p><strong>As of:</strong> 19.09.2024</p>
|
||||
</header>
|
||||
<section>
|
||||
<h2>1. General Information</h2>
|
||||
@@ -53,7 +53,7 @@
|
||||
<h2>3. Data Collection</h2>
|
||||
<h3>3.1 The following categories of personal data are processed</h3>
|
||||
<ul>
|
||||
<li>Names: Username, first and last names as well as your digital signature</li>
|
||||
<li>Names: First and last names as well as your digital signature</li>
|
||||
<li>Contact details: Phone number, mobile phone number, and email address</li>
|
||||
<li>Technical data: IP address, time of access, or access attempts</li>
|
||||
</ul>
|
||||
@@ -153,6 +153,133 @@
|
||||
<a href="https://www.bfdi.bund.de/DE/Service/Anschriften/Laender/Laender-node.html">Laender-node.html</a>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>6. Whistleblower System</h2>
|
||||
<p>
|
||||
Compliance with legal regulations and internal guidelines, including our Code of Conduct and the Code of
|
||||
Conduct for Business Partners, is our (the data processing entity's) top priority. This applies both to our
|
||||
own business operations and to our supply chains.
|
||||
</p>
|
||||
<p>
|
||||
It is important to us to identify risks early and avoid violations. We aim to take appropriate measures in a
|
||||
timely manner to prevent potential harm to affected persons, customers, employees, business partners, and
|
||||
our corporate group.
|
||||
</p>
|
||||
<p>
|
||||
For this reason, we have established an independent, neutral, and confidential whistleblower system that
|
||||
enables internal and external whistleblowers to submit reports, including anonymously. Through our
|
||||
transparent complaint procedure, we offer the greatest possible protection, especially to the affected
|
||||
persons, whistleblowers, and employees involved in investigating reported incidents.
|
||||
</p>
|
||||
<p>
|
||||
Under this procedure, any actual or alleged violations of legal requirements, our Code of Conduct, or the
|
||||
Code of Conduct for Business Partners may be reported. Human rights or environmental risks, as well as
|
||||
breaches of duty along the entire supply chain of our group companies and in our own business operations,
|
||||
can also be the subject of a report.
|
||||
</p>
|
||||
<p>
|
||||
Standardized and swift processes, as well as confidential and professional handling of the reports by
|
||||
internal experts, form the basis of this fair procedure. Discrimination or punishment of whistleblowers and
|
||||
individuals responsible for handling complaints and reports will not be tolerated.
|
||||
</p>
|
||||
|
||||
<h3>6.1 Purpose and Legal Basis of Data Processing</h3>
|
||||
<p>
|
||||
The purpose of processing personal data is to manage the whistleblower system, which also includes
|
||||
identifying serious violations or potential violations of applicable law and other serious matters. The
|
||||
processing of this data is necessary to comply with legal obligations imposed on us, in accordance with Art.
|
||||
6 para. 1 sentence 1 lit. c) GDPR. This refers to the law that enhances the protection of whistleblowers
|
||||
(Whistleblower Protection Act - HinSchG).
|
||||
</p>
|
||||
<p>
|
||||
Additionally, the processing serves the legitimate interest of identifying serious violations or potential
|
||||
violations of applicable law and other serious matters, in accordance with Art. 6 para. 1 sentence 1 lit. f)
|
||||
GDPR.
|
||||
</p>
|
||||
<p>
|
||||
Regarding the processing of special categories of personal data, this is necessary based on the
|
||||
Whistleblower Protection Act for reasons of significant public interest, in accordance with Art. 9 para. 2
|
||||
lit. g) GDPR. The processing of such special data is carried out in accordance with Art. 9 para. 2 lit. f)
|
||||
GDPR in conjunction with Art. 6 para. 1 sentence 1 lit. f) GDPR to establish, exercise, or defend legal
|
||||
claims.
|
||||
</p>
|
||||
<p>
|
||||
Affected persons are those about whom a report is made. These can be employees, contractors, or other
|
||||
individuals in a business relationship with the data processing entity. Furthermore, we process personal
|
||||
data of the whistleblower if they provide their contact details or other identifying information.
|
||||
Whistleblowers should be aware that we may process personal data about them during the handling of the
|
||||
reported case.
|
||||
</p>
|
||||
|
||||
<h3>6.2 Categories of Personal Data</h3>
|
||||
<p>
|
||||
Reports can be made anonymously, in which case no personal data of the reporting person will be processed.
|
||||
The type of personal data processed depends on the information provided. If the reporting person provides
|
||||
personal data about another individual, including the reported individual or persons, that data will also be
|
||||
processed. The following categories of personal data may be processed:
|
||||
</p>
|
||||
<ul>
|
||||
<li>General personal data (e.g., first name, last name, address, email address, phone number, etc.)</li>
|
||||
<li>Personal data related to criminal convictions or suspicions</li>
|
||||
<li>Special categories of personal data (information about racial or ethnic origin, political opinions,
|
||||
religious or philosophical beliefs, trade union membership, health data, and information about a
|
||||
person's sex life or sexual orientation)</li>
|
||||
</ul>
|
||||
<p>
|
||||
We ask the reporting person to only provide information relevant to the case and to avoid reporting
|
||||
sensitive information unless it is essential for handling the reported case.
|
||||
</p>
|
||||
|
||||
<h3>6.3 Obligation to Provide Personal Data</h3>
|
||||
<p>
|
||||
It is not mandatory to provide the personal data mentioned in section 6.2, as anonymous reporting is also
|
||||
possible. However, please note that we may be unable to process the report if no personal data is provided.
|
||||
</p>
|
||||
|
||||
<h3>6.4 Recipients of Personal Data</h3>
|
||||
<p>
|
||||
Reports are logged in the system of the data processing entity as cases. After evaluation, these cases are
|
||||
forwarded internally to the relevant departments, and follow-up actions may be initiated. If a report
|
||||
involves one of the group companies of the data processing entity, the relevant cases are forwarded to the
|
||||
responsible individuals at the respective company, who will then conduct an internal evaluation and take
|
||||
action if necessary. When transferring personal data, the principle of data minimization is observed,
|
||||
meaning only the data strictly necessary for handling the report is shared.
|
||||
</p>
|
||||
<p>
|
||||
Personal data of the whistleblower will be shared with authorities when necessary to address serious
|
||||
violations or issues, or to safeguard the right to defense of the affected persons. In other cases, personal
|
||||
data of the whistleblower will only be shared with their consent. Data about persons other than the
|
||||
whistleblower will only be shared in connection with the investigation of a reported case or to address
|
||||
serious violations or issues.
|
||||
</p>
|
||||
<p>
|
||||
The reporting platform is provided by the processor WhistleB Whistleblowing Centre AB, based in Stockholm,
|
||||
Sweden. Further information about WhistleB and the corresponding terms of use can be found at:
|
||||
<a
|
||||
href="https://report.whistleb.com/content/documents/whistleb_terms_of_use.pdf">whistleb_terms_of_use.pdf</a>
|
||||
</p>
|
||||
|
||||
<h3>6.5 Retention Period</h3>
|
||||
<p>
|
||||
Personal data that is found to be irrelevant to the processing of a reported case, as well as reports deemed
|
||||
unfounded, will be immediately classified as "not relevant." In this case, the personal reference is removed
|
||||
unless the report was anonymous from the outset. To meet the legally required documentation obligations and
|
||||
deletion periods pursuant to § 11 para. 1 and para. 5 HinSchG, the report is initially archived without
|
||||
personal reference but is not yet deleted. Archived cases serve solely to fulfill these documentation
|
||||
obligations and can no longer be used for further processing.
|
||||
</p>
|
||||
<p>
|
||||
Reports and personal data collected during the processing of a report form the basis for further handling
|
||||
and are anonymized as soon as possible. However, if it is necessary to take follow-up actions pursuant to §§
|
||||
3 para. 8 and 18 HinSchG, it may be necessary to deviate from anonymization, whether due to official orders
|
||||
or to protect legal claims. In such cases, pseudonymization is generally sought, unless other directives
|
||||
apply, such as a court order. Documentation is deleted three years after the conclusion of the process, but
|
||||
it may be retained longer if required to meet the requirements of this law or other legal provisions, as
|
||||
long as it remains necessary and appropriate.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -37,6 +37,10 @@ Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "EnvelopeGenerator.Form", "E
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnvelopeGenerator.PdfEditor", "EnvelopeGenerator.PdfEditor\EnvelopeGenerator.PdfEditor.csproj", "{211619F5-AE25-4BA5-A552-BACAFE0632D3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnvelopeGenerator.DependencyInjection", "EnvelopeGenerator.DependencyInjection\EnvelopeGenerator.DependencyInjection.csproj", "{B97DE7DD-3190-4A84-85E9-E57AD735BE61}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnvelopeGenerator.Finalizer", "EnvelopeGenerator.Finalizer\EnvelopeGenerator.Finalizer.csproj", "{C4970E6C-DB2E-48C5-B3C5-2AF589405ED9}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -91,6 +95,14 @@ Global
|
||||
{211619F5-AE25-4BA5-A552-BACAFE0632D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{211619F5-AE25-4BA5-A552-BACAFE0632D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{211619F5-AE25-4BA5-A552-BACAFE0632D3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B97DE7DD-3190-4A84-85E9-E57AD735BE61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B97DE7DD-3190-4A84-85E9-E57AD735BE61}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B97DE7DD-3190-4A84-85E9-E57AD735BE61}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B97DE7DD-3190-4A84-85E9-E57AD735BE61}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C4970E6C-DB2E-48C5-B3C5-2AF589405ED9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C4970E6C-DB2E-48C5-B3C5-2AF589405ED9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C4970E6C-DB2E-48C5-B3C5-2AF589405ED9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C4970E6C-DB2E-48C5-B3C5-2AF589405ED9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -111,6 +123,8 @@ Global
|
||||
{A9F9B431-BB9B-49B8-9E2C-0703634A653A} = {E3C758DC-914D-4B7E-8457-0813F1FDB0CB}
|
||||
{6D56C01F-D6CB-4D8A-BD3D-4FD34326998C} = {E3C758DC-914D-4B7E-8457-0813F1FDB0CB}
|
||||
{211619F5-AE25-4BA5-A552-BACAFE0632D3} = {9943209E-1744-4944-B1BA-4F87FC1A0EEB}
|
||||
{B97DE7DD-3190-4A84-85E9-E57AD735BE61} = {E3C758DC-914D-4B7E-8457-0813F1FDB0CB}
|
||||
{C4970E6C-DB2E-48C5-B3C5-2AF589405ED9} = {E3C758DC-914D-4B7E-8457-0813F1FDB0CB}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {73E60370-756D-45AD-A19A-C40A02DACCC7}
|
||||
|
||||
Reference in New Issue
Block a user