Files
elwig/Elwig/Documents/Document.cs

161 lines
6.2 KiB
C#

using System;
using System.Threading.Tasks;
using System.IO;
using Elwig.Helpers;
using System.Collections.Generic;
using System.Linq;
using Elwig.Helpers.Printing;
namespace Elwig.Documents {
public abstract partial class Document : IDisposable {
public static string Name => "Dokument";
protected static readonly double GenerationProportion = 0.125;
protected TempFile? _pdfFile = null;
protected string? _pdfPath;
protected string? PdfPath => _pdfPath ?? _pdfFile?.FilePath;
public bool ShowFoldMarks = App.Config.Debug;
public bool DoubleSided = false;
public string DataPath;
public int CurrentNextSeason;
public string? DocumentId;
public string Title;
public string Author;
public string Header;
public string Footer;
public DateTime Date;
public Document(string title) {
var c = App.Client;
DataPath = App.DataPath;
CurrentNextSeason = Utils.CurrentNextSeason;
Title = title;
Author = c.NameFull;
Header = $"<div class='name'>{c.Name}</div><div class='suffix'>{c.NameSuffix}</div><div class='type'>{c.NameTypeFull}</div>";
Footer = Utils.GenerateFooter("<br/>", " \u00b7 ")
.Item(c.NameFull).NextLine()
.Item(c.Address).Item($"{c.Plz} {c.Ort}").Item("Österreich").Item("Tel.", c.PhoneNr).Item("Fax", c.FaxNr).NextLine()
.Item(c.EmailAddress != null ? $"<a href=\"mailto:{c.Name} {c.NameSuffix} <{c.EmailAddress}>\">{c.EmailAddress}</a>" : null)
.Item(c.Website != null ? $"<a href=\"http://{c.Website}/\">{c.Website}</a>" : null)
.Item("Betriebs-Nr.", c.LfbisNr).Item("UID", c.UstIdNr).NextLine()
.Item("BIC", c.Bic).Item("IBAN", c.Iban)
.ToString();
Date = DateTime.Today;
}
~Document() {
Dispose();
}
public void Dispose() {
_pdfFile?.Dispose();
_pdfFile = null;
GC.SuppressFinalize(this);
}
public static Document Merge(IEnumerable<Document> docs) {
return new MergedDocument(docs);
}
public static Document FromPdf(string path) {
return new PdfDocument(path);
}
private async Task<string> Render() {
string name;
if (this is BusinessLetter) {
name = "BusinessLetter";
} else if (this is DeliveryNote) {
name = "DeliveryNote";
} else if (this is CreditNote) {
name = "CreditNote";
} else if (this is DeliveryJournal) {
name = "DeliveryJournal";
} else if (this is Letterhead) {
name = "Letterhead";
} else if (this is DeliveryConfirmation) {
name = "DeliveryConfirmation";
} else if (this is MemberDataSheet) {
name = "MemberDataSheet";
} else {
throw new InvalidOperationException("Invalid document object");
}
return await Render(name);
}
private async Task<string> Render(string name) {
return await Html.CompileRenderAsync(name, this); ;
}
public async Task Generate(IProgress<double>? progress = null) {
progress?.Report(0.0);
if (this is PdfDocument) {
// nothing to do
} else if (this is MergedDocument m) {
var pdf = new TempFile("pdf");
var tmpHtmls = new List<TempFile>();
var tmpFiles = new List<string>();
var n = m.Documents.Count();
int i = 0;
foreach (var doc in m.Documents) {
if (doc is PdfDocument) {
tmpFiles.Add(doc.PdfPath!);
continue;
}
var tmpHtml = new TempFile("html");
await File.WriteAllTextAsync(tmpHtml.FilePath, await doc.Render(), Utils.UTF8);
tmpHtmls.Add(tmpHtml);
tmpFiles.Add((doc is Letterhead ? "#" : "") + tmpHtml.FileName);
i++;
progress?.Report(GenerationProportion * 100 * i / n);
}
progress?.Report(GenerationProportion * 100);
await Pdf.Convert(tmpFiles, pdf.FileName, DoubleSided, new Progress<double>(v => progress?.Report(GenerationProportion * 100 + v * (1 - GenerationProportion))));
foreach (var tmp in tmpHtmls) {
tmp.Dispose();
}
_pdfFile = pdf;
} else {
var pdf = new TempFile("pdf");
using (var tmpHtml = new TempFile("html")) {
await File.WriteAllTextAsync(tmpHtml.FilePath, await Render(), Utils.UTF8);
progress?.Report(50.0);
await Pdf.Convert(tmpHtml.FilePath, pdf.FilePath, DoubleSided);
}
_pdfFile = pdf;
}
progress?.Report(100.0);
}
public void SaveTo(string pdfPath) {
if (PdfPath == null) throw new InvalidOperationException("Pdf file has not been generated yet");
File.Copy(PdfPath, pdfPath, true);
}
public async Task Print(int copies = 1) {
if (PdfPath == null) throw new InvalidOperationException("Pdf file has not been generated yet");
await Pdf.Print(PdfPath, copies);
}
public void Show() {
if (_pdfFile == null) throw new InvalidOperationException("Pdf file has not been generated yet");
Pdf.Show(_pdfFile.NewReference(), Title + (this is BusinessDocument b ? $" - {b.Member.Name}" : ""));
}
private class MergedDocument(IEnumerable<Document> docs) : Document("Mehrere Dokumente") {
public IEnumerable<Document> Documents = docs;
}
private class PdfDocument : Document {
public PdfDocument(string pdfPath) :
base(Path.GetFileNameWithoutExtension(pdfPath)) {
_pdfPath = pdfPath;
}
}
}
}