diff --git a/core/PaymentReceiptProcess.cs b/core/PaymentReceiptProcess.cs index a9d746e..fc5896f 100644 --- a/core/PaymentReceiptProcess.cs +++ b/core/PaymentReceiptProcess.cs @@ -18,6 +18,7 @@ namespace dezentrale.core public interface IPaymentReceiptProcessData { List MemberList { get; set; } + bool AllMembers { get; set; } string DataTemplate { get; set; } IntermediateFormat DataFormat { get; set; } @@ -28,6 +29,7 @@ namespace dezentrale.core string StartDateString { get; } string EndDateString { get; } bool SendEmail { get; set; } + bool WriteProtectPdf { get; set; } } //In order to be able to ReplaceReflect, we need to have the SvgData and SvgFileName field separated in a class @@ -58,7 +60,7 @@ namespace dezentrale.core this.data = data; Caption = "Generate receipt PDF for each membership payment"; - Steps = 5; + Steps = 6; } //! \short Run receipt generation process @@ -70,7 +72,21 @@ namespace dezentrale.core uint step = 0; try { - List memberList = data.MemberList ?? Program.members.Entries; + List memberList; + bool allMembers = data.AllMembers; + if (data.MemberList == null || data.MemberList.Count < 1) + { + if(!data.AllMembers) + { + LogTarget.LogLine($"No member list provided", LogEvent.ELogLevel.Error, "PaymentReceiptProcess"); + return false; + } + memberList = Program.members.Entries; + } else + { + memberList = allMembers ? Program.members.Entries : data.MemberList; + LogTarget.LogLine($"Processing {memberList.Count} entries (AllMembers={allMembers})", LogEvent.ELogLevel.Error, "PaymentReceiptProcess"); + } // In preparation to send E-Mail and combine multiple files into one mail later, // we're using a List of KVP with key = filename, value = member reference @@ -107,7 +123,10 @@ namespace dezentrale.core Member m = memberList.Find(x => x.Number == mt.MemberNumber); if(m == null) { - LogTarget.LogLine($"Cannot find member {mt.MemberNumber} referenced in MoneyTransfer {mt.Id} (from {mt.ValutaDate})", LogEvent.ELogLevel.Error, "PaymentReceiptProcess"); + //this is only an error, if all members are selected in the dialog, we can check this. + if(allMembers) + LogTarget.LogLine($"Cannot find member {mt.MemberNumber} referenced in MoneyTransfer {mt.Id} (from {mt.ValutaDate})", LogEvent.ELogLevel.Error, "PaymentReceiptProcess"); + //but in every case, we need to skip this MoneyTransfer. continue; } if(!m.MoneyTransfersIds.Contains(mt.Id)) @@ -141,8 +160,14 @@ namespace dezentrale.core ImportExportBase.RunProcess("pdflatex", $"\"{sourceFile}\"", ".", LogTarget); break; } - } + if(data.WriteProtectPdf && data.DataFormat != IntermediateFormat.Text) + { + //Write-protecting pdf + ImportExportBase.RunProcess("qpdf", $"--encrypt \"\" \"random-owner-pw\" 256 --modify=none -- \"{pdf}\" \"{pdf}.writeprotect\"", ".", LogTarget); + File.Replace(pdf, pdf + ".writeprotect", pdf + ".writable"); + } + } LogTarget.StepStarted(++step, "E-Mail the PDFs to the members"); if (data.SendEmail) diff --git a/view/frmMain.cs b/view/frmMain.cs index 1ad65ac..9a9453a 100644 --- a/view/frmMain.cs +++ b/view/frmMain.cs @@ -121,9 +121,10 @@ namespace dezentrale.view int totalHours = (int) now.Subtract(Program.config.LastDbImport).TotalHours; int totalDays = totalHours / 24; if (totalHours >= 8) - { + { + totalHours %= 24; string timeSpan = $"{totalDays} d, {totalHours} h"; - totalHours %= 24; + if (Program.config.DbChangedSinceExport) { MessageBox.Show( "Warning: There are local changes to DB since last export!\r\n" diff --git a/view/frmPaymentReceipts.cs b/view/frmPaymentReceipts.cs index 32ff8cb..75be6f0 100644 --- a/view/frmPaymentReceipts.cs +++ b/view/frmPaymentReceipts.cs @@ -32,6 +32,7 @@ namespace dezentrale.view public class frmPaymentReceipts : FormWithOkCancel, IPaymentReceiptProcessData { public List MemberList { get; set; } = null; + public bool AllMembers { get; set; } = false; public string DataTemplate { get; set; } = ""; public IntermediateFormat DataFormat { get; set; } = IntermediateFormat.Text; public string OutputDirectory { get; set; } = ""; @@ -41,6 +42,7 @@ namespace dezentrale.view public bool SendEmail { get; set; } = false; public string StartDateString { get { return StartDate.ToShortDateString(); } } public string EndDateString { get { return EndDate .ToShortDateString(); } } + public bool WriteProtectPdf { get; set; } = false; private TextBox tbTemplate; private ComboBox cbDataFormat; @@ -51,13 +53,14 @@ namespace dezentrale.view private RadioButton optAllMembers; private RadioButton optSelectedMembers; private CheckBox chkSendEmail; + private CheckBox chkWriteProtectPdf; public frmPaymentReceipts() { DialogResult = DialogResult.Cancel; this.StartPosition = FormStartPosition.CenterParent; - this.Size = new System.Drawing.Size(483, 310); - this.MinimumSize = new System.Drawing.Size(455, 310); + this.Size = new System.Drawing.Size(483, 320); + this.MinimumSize = new System.Drawing.Size(455, 320); this.Text = "Generate payment receipts"; this.Controls.Add(new Label() { @@ -98,6 +101,10 @@ namespace dezentrale.view }); foreach (IntermediateFormat fmt in Enum.GetValues(typeof(IntermediateFormat))) cbDataFormat.Items.Add(fmt); + cbDataFormat.SelectedValueChanged += (sender, e) => + { + chkWriteProtectPdf.Enabled = (IntermediateFormat)cbDataFormat.SelectedItem != IntermediateFormat.Text; + }; this.Controls.Add(new Label() { @@ -201,6 +208,12 @@ namespace dezentrale.view Width = 300, Location = new Point(lm + 113, 8 * line + tm), }); + this.Controls.Add(chkWriteProtectPdf = new CheckBox() + { + Text = "Ausgabe schreibschützen (QPDF erforderlich)", + Width = 300, + Location = new Point(lm + 113, 9 * line + tm), + }); AddOkCancel(this, btnOK_Click, btnCancel_Click); @@ -215,13 +228,17 @@ namespace dezentrale.view dtStartDate.Value = StartDate; dtEndDate.Value = EndDate; if (MemberList != null && MemberList.Count > 0) - optSelectedMembers.Checked = true; + { + optAllMembers.Checked = AllMembers; + optSelectedMembers.Checked = !AllMembers; + } else { optAllMembers.Checked = true; optSelectedMembers.Enabled = false; } chkSendEmail.Checked = SendEmail; + chkWriteProtectPdf.Checked = WriteProtectPdf; }; } @@ -263,6 +280,7 @@ namespace dezentrale.view private void btnOK_Click(object sender, EventArgs e) { + AllMembers = optAllMembers.Checked; DataTemplate = tbTemplate.Text; DataFormat = (IntermediateFormat) cbDataFormat.SelectedItem; OutputDirectory = tbOutputDirectory.Text; @@ -271,6 +289,7 @@ namespace dezentrale.view EndDate = dtEndDate.Value.AddSeconds(24*60*60 - 1); if (optSelectedMembers.Checked != true) MemberList = null; SendEmail = chkSendEmail.Checked; + WriteProtectPdf = chkWriteProtectPdf.Checked; DialogResult = DialogResult.OK; this.Close(); }