200826PX Made PaymentReceipts more general as it depends on the template and installed pdf converter versions

This commit is contained in:
phantomix 2020-08-26 18:18:16 +02:00
parent 63680d6f7e
commit dcf3b05fff
4 changed files with 172 additions and 39 deletions

View File

@ -7,26 +7,37 @@ using dezentrale.model.money;
namespace dezentrale.core
{
public enum IntermediateFormat
{
Text,
SvgInkscape092,
SvgInkscapeNew,
Latex
}
public interface IPaymentReceiptProcessData
{
string SvgTemplate { get; set; }
string OutputDirectory { get; set; }
string FileNamePattern { get; set; }
DateTime StartDate { get; set; }
DateTime EndDate { get; set; }
string DataTemplate { get; set; }
IntermediateFormat DataFormat { get; set; }
string OutputDirectory { get; set; }
string FileNamePattern { get; set; }
DateTime StartDate { get; set; }
DateTime EndDate { get; set; }
}
//In order to be able to ReplaceReflect, we need to have the SvgData and SvgFileName field separated in a class
class SvgFile : ReplaceReflectEntity<SvgFile>
class IntermediateFile : ReplaceReflectEntity<IntermediateFile>
{
public string SvgFileName { get; set; } = "";
public string SvgData { get; set; } = "";
public SvgFile() { }
public SvgFile(string fileName)
public string FileName { get; set; } = "";
public string Data { get; set; } = "";
public IntermediateFile() { }
public IntermediateFile(string fileName)
{
SvgFileName = fileName;
SvgData = File.ReadAllText(fileName);
FileName = fileName;
Data = File.ReadAllText(fileName);
}
}
@ -55,12 +66,12 @@ namespace dezentrale.core
uint step = 0;
try
{
List<string> svgOutputFiles = new List<string>();
List<string> intermediateFiles = new List<string>();
LogTarget.StepStarted(step, "Loading source SVG template");
SvgFile svgTemplate = new SvgFile(data.SvgTemplate);
svgTemplate.SvgFileName = data.FileNamePattern;
LogTarget.LogLine($"Loaded \"{data.SvgTemplate}\" ({svgTemplate.SvgData.Length} characters) into memory.", LogEvent.ELogLevel.Info, "PaymentReceiptProcess");
IntermediateFile svgTemplate = new IntermediateFile(data.DataTemplate);
svgTemplate.FileName = data.FileNamePattern;
LogTarget.LogLine($"Loaded \"{data.DataTemplate}\" ({svgTemplate.Data.Length} characters) into memory.", LogEvent.ELogLevel.Info, "PaymentReceiptProcess");
LogTarget.StepStarted(++step, "Filtering MoneyTransfers for the given timeframe");
@ -86,16 +97,28 @@ namespace dezentrale.core
LogTarget.LogLine($"Member {m.Nickname} ({m.Number}) doesn't reference MoneyTransfer {mt.Id} (from {mt.ValutaDate})", LogEvent.ELogLevel.Error, "PaymentReceiptProcess");
continue;
}
SvgFile output = svgTemplate.ReplaceReflect(mt).ReplaceReflect(m);
LogTarget.LogLine($"Generating file \"{output.SvgFileName}\"", LogEvent.ELogLevel.Info, "PaymentReceiptProcess");
File.WriteAllText(output.SvgFileName, output.SvgData);
svgOutputFiles.Add(output.SvgFileName);
IntermediateFile output = svgTemplate.ReplaceReflect(mt).ReplaceReflect(m);
LogTarget.LogLine($"Generating file \"{output.FileName}\"", LogEvent.ELogLevel.Info, "PaymentReceiptProcess");
File.WriteAllText(output.FileName, output.Data);
intermediateFiles.Add(output.FileName);
}
LogTarget.StepStarted(++step, "Converting SVGs to PDF using Inkscape");
foreach (string svg in svgOutputFiles)
LogTarget.StepStarted(++step, "Converting intermediate files to PDF using Inkscape");
foreach (string iFile in intermediateFiles)
{
ImportExportBase.RunProcess("inkscape", $"{svg} --export-filename={svg}.pdf ", ".", LogTarget);
switch(data.DataFormat)
{
case IntermediateFormat.Text: break;
case IntermediateFormat.SvgInkscape092:
ImportExportBase.RunProcess("inkscape", $"{iFile} --export-pdf={iFile}.pdf", ".", LogTarget);
break;
case IntermediateFormat.SvgInkscapeNew:
ImportExportBase.RunProcess("inkscape", $"{iFile} --export-type=pdf --export-filename={iFile}.pdf", ".", LogTarget);
break;
case IntermediateFormat.Latex:
ImportExportBase.RunProcess("pdflatex", $"{iFile}", ".", LogTarget);
break;
}
}
LogTarget.StepStarted(++step, "E-Mail the PDFs to the members");

View File

@ -4,10 +4,11 @@ using System.Linq;
using System.Net.Mail;
using System.Reflection;
using System.Text;
using dezentrale.core;
namespace dezentrale.model
{
public class FormMail
public class FormMail : ReplaceReflectEntity<FormMail>
{
public string To { get; set; } = "{Nickname} <{EMail}>";
public string Subject { get; set; }
@ -25,7 +26,7 @@ namespace dezentrale.model
}
}
public FormMail ReplaceReflect(object o)
/*public FormMail ReplaceReflect(object o)
{
FormMail ret = new FormMail(this);
@ -69,7 +70,7 @@ namespace dezentrale.model
}
}
return ret;
}
}*/
public LogSubEvent Send(object replaceReflect = null, List<string> files = null)
{

View File

@ -241,14 +241,15 @@ namespace dezentrale.view
}
private void mnuMain_Payments_Receipts(object sender, EventArgs e)
{
frmPaymentReceipts receipts = new frmPaymentReceipts();
frmPaymentReceipts receipts = new frmPaymentReceipts()
{
StartDate = new DateTime(2020, 01, 01),
EndDate = new DateTime(2020, 12, 31),
FileNamePattern = "Member{MemberNumber}-{ValutaDateString}-{AmountString}{Currency}"
};
DialogResult dr = receipts.ShowDialog();
if(dr == DialogResult.OK)
{
receipts.SvgTemplate = "dezentrale-beitragsquittung-template.svg";
receipts.StartDate = new DateTime(2020, 01, 01);
receipts.EndDate = new DateTime(2020, 12, 31);
receipts.FileNamePattern = "Member{MemberNumber}-{ValutaDateString}-{AmountString}{Currency}.svg";
{
PaymentReceiptProcess rec = new PaymentReceiptProcess(receipts);
frmProcessWithLog frmRec = new frmProcessWithLog(rec, true);
dr = frmRec.ShowDialog();

View File

@ -12,14 +12,16 @@ namespace dezentrale.view
public class frmPaymentReceipts : FormWithOkCancel, IPaymentReceiptProcessData
{
public string SvgTemplate { get; set; } = "";
public string OutputDirectory { get; set; } = "";
public string FileNamePattern { get; set; } = "{Number}-{Date}";
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public string DataTemplate { get; set; } = "";
public IntermediateFormat DataFormat { get; set; } = IntermediateFormat.Text;
public string OutputDirectory { get; set; } = "";
public string FileNamePattern { get; set; } = "{Number}-{Date}";
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
private TextBox tbSvgTemplate;
private TextBox tbTemplate;
private ComboBox cbDataFormat;
private TextBox tbOutputDirectory;
private TextBox tbFileNamePattern;
private DateTimePicker dtStartDate;
@ -27,11 +29,117 @@ namespace dezentrale.view
public frmPaymentReceipts()
{
DialogResult = DialogResult.Cancel;
this.StartPosition = FormStartPosition.CenterParent;
this.Size = new System.Drawing.Size(500, 400);
this.Text = "Generate payment receipts";
this.Controls.Add(new Label()
{
Text = "Input template:",
Location = new Point(lm, 0 * line + tm + labelOffs),
Size = new Size(110, labelHeight),
TextAlign = ContentAlignment.BottomRight,
});
this.Controls.Add(tbTemplate = new TextBox()
{
Location = new Point(lm + 113, 0 * line + tm),
Width = 200,
});
Button btnBrowseTemplate;
this.Controls.Add(btnBrowseTemplate = new Button()
{
Text = "...",
Location = new Point(lm + 333, 0 * line + tm),
Width = 40,
});
btnBrowseTemplate.Click += btnBrowseTemplate_Click;
this.Controls.Add(new Label()
{
Text = "Data format:",
Location = new Point(lm, 1 * line + tm + labelOffs),
Size = new Size(110, labelHeight),
TextAlign = ContentAlignment.BottomRight,
});
this.Controls.Add(cbDataFormat = new ComboBox()
{
DropDownStyle = ComboBoxStyle.DropDownList,
Location = new Point(lm + 113, 1 * line + tm),
Width = 200,
});
foreach (IntermediateFormat fmt in Enum.GetValues(typeof(IntermediateFormat)))
cbDataFormat.Items.Add(fmt);
this.Controls.Add(new Label()
{
Text = "Output directory:",
Location = new Point(lm, 2 * line + tm + labelOffs),
Size = new Size(110, labelHeight),
TextAlign = ContentAlignment.BottomRight,
});
this.Controls.Add(tbOutputDirectory = new TextBox()
{
Location = new Point(lm + 113, 2 * line + tm),
Width = 200,
});
Button btnBrowseOutputDir;
this.Controls.Add(btnBrowseOutputDir = new Button()
{
Text = "...",
Location = new Point(lm + 333, 2 * line + tm),
Width = 40,
});
btnBrowseOutputDir.Click += btnBrowseOutputDir_Click;
this.Controls.Add(new Label()
{
Text = "Filename pattern:",
Location = new Point(lm, 3 * line + tm + labelOffs),
Size = new Size(110, labelHeight),
TextAlign = ContentAlignment.BottomRight,
});
this.Controls.Add(tbFileNamePattern = new TextBox()
{
Location = new Point(lm + 113, 3 * line + tm),
Width = 240,
});
AddOkCancel(this, btnOK_Click, btnCancel_Click);
//We must run the filling of the data fields in the load event, as they
//might have been changed after the constructor is executed
this.Shown += (sender, e) =>
{
tbTemplate.Text = DataTemplate;
cbDataFormat.SelectedItem = DataFormat;
tbOutputDirectory.Text = OutputDirectory;
};
}
private void btnBrowseTemplate_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
DialogResult dr = ofd.ShowDialog();
if(dr == DialogResult.OK)
{
tbTemplate.Text = ofd.FileName;
}
}
private void btnBrowseOutputDir_Click(object sender, EventArgs e)
{
FolderBrowserDialog fbd = new FolderBrowserDialog();
DialogResult dr = fbd.ShowDialog();
if (dr == DialogResult.OK)
{
tbOutputDirectory.Text = fbd.SelectedPath;
}
}
private void btnOK_Click(object sender, EventArgs e)
{
DataTemplate = tbTemplate.Text;
DialogResult = DialogResult.OK;
this.Close();
}