Compare commits

...

24 Commits

Author SHA1 Message Date
e9e4c75edd Bump version to 0.2.1 2023-09-13 23:37:26 +02:00
ff1a4e7182 Documents: Add ShowFoldMarks flag 2023-09-13 23:22:35 +02:00
1e9cad6de7 DeliveryAdminWindow: Use last scale error as default manual weighing reason 2023-09-13 23:19:04 +02:00
62fe087598 DeliveryAdminWindow: Hopefully fix 'Erste Übernahme' bug 2023-09-13 22:57:21 +02:00
7f01b85878 HelpersUtilsTest: fix file encoding 2023-09-13 22:04:01 +02:00
a659d07db2 Config: add debug flag 2023-09-13 22:02:50 +02:00
b2a78907cf Bump version to 0.2.0 2023-09-12 22:52:28 +02:00
7bcf532b26 DeliveryAdminWindow: Verschlimmbesserung 2023-09-12 22:51:03 +02:00
595f9a049c ManualWeighingDialog: Do not require Reason 2023-09-12 22:51:03 +02:00
80ed90941d Include all files in Documents except .cs files 2023-09-12 21:50:56 +02:00
77cee53f2d MainWindow: Cleanup and move parts to TestWindow 2023-09-12 21:41:00 +02:00
1a673f4b3a Documents: Add CreditNote 2023-09-12 21:40:33 +02:00
5ad8c88319 Models: Add Credit 2023-09-12 21:40:04 +02:00
30aaa64f59 BusinessDocument: Add UseBillingAddress flag 2023-09-12 13:49:11 +02:00
352bf840c3 DeliveryAdminWindow: Add user confirmation on closing when creating 2023-09-10 23:03:42 +02:00
898cece0d3 DeliveryAdminWindow: Small quality of life fixes 2023-09-09 21:33:37 +02:00
0b05cc4e10 Documents: move styles 2023-09-08 13:38:26 +02:00
74fa08e95d Windows: Remove '-verwaltung' from window names 2023-09-08 13:31:16 +02:00
bc6148624c DeliveryAdminWindow: Add export option for BKI 2023-09-08 12:44:29 +02:00
f5f00a7739 Export: Add Ebics and improve Bki export 2023-09-08 00:43:53 +02:00
2de4739e9d Models: Small payment fixes 2023-09-07 16:54:33 +02:00
47e8ab7e62 Export/Bki: Add 0.0 to KMW output 2023-09-07 16:40:21 +02:00
8a678509c5 Utils: Add UTF8 encoding without BOM 2023-09-07 16:39:49 +02:00
de53bfdd2b IAddress: Add IAddress 2023-09-07 13:49:56 +02:00
48 changed files with 989 additions and 217 deletions

View File

@@ -84,8 +84,8 @@ namespace Elwig {
var list = new List<IScale>();
foreach (var s in Config.Scales) {
var id = s[0];
try {
var id = s[0];
var type = s[1]?.ToLower();
var model = s[2];
var cnx = s[3];
@@ -99,6 +99,7 @@ namespace Elwig {
throw new ArgumentException($"Invalid scale type: \"{type}\"");
}
} catch (Exception e) {
list.Add(new InvalidScale(id));
MessageBox.Show($"Unable to create scale {s[0]}:\n\n{e.Message}", "Scale Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}

View File

@@ -9,24 +9,21 @@ namespace Elwig.Dialogs {
public int Weight = 0;
public string? Reason = null;
public ManualWeighingDialog() {
public ManualWeighingDialog(string? reason = null) {
InitializeComponent();
ReasonInput.Text = reason;
}
private void ConfirmButton_Click(object sender, RoutedEventArgs evt) {
DialogResult = true;
Weight = int.Parse(WeightInput.Text);
Reason = Regex.Replace(ReasonInput.Text, @"\s+", "").Trim();
if (Reason == "") {
Reason = null;
} else if (!Reason.EndsWith(".") || !Reason.EndsWith("!") || !Reason.EndsWith("?")) {
Reason += ".";
}
Reason = Regex.Replace(ReasonInput.Text, @"\s+", " ").Trim();
if (Reason == "") Reason = null;
Close();
}
private void UpdateButtons() {
ConfirmButton.IsEnabled = WeightInput.Text.Length > 0 && ReasonInput.Text.Trim().Length > 0;
ConfirmButton.IsEnabled = WeightInput.Text.Length > 0;
}
private void WeightInput_TextChanged(object sender, TextChangedEventArgs evt) {

View File

@@ -5,8 +5,9 @@ namespace Elwig.Documents {
public Member Member;
public bool IncludeSender = false;
public string Aside { get; set; }
public string? Location { get; set; }
public bool UseBillingAddress = false;
public string Aside;
public string? Location;
public BusinessDocument(string title, Member m, bool includeSender = false) : base(title) {
Member = m;
@@ -24,10 +25,11 @@ namespace Elwig.Documents {
public string Address {
get {
var b = Member.BillingAddress;
var plz = (b == null) ? Member.PostalDest.AtPlz : b.PostalDest.AtPlz;
if (b != null) {
if (b != null && UseBillingAddress) {
var plz = b.PostalDest.AtPlz;
return $"{b.Name}\n{Member.AdministrativeName}\n{b.Address}\n{plz.Plz} {plz.Dest}\nÖsterreich";
} else {
var plz = Member.PostalDest.AtPlz;
return $"{Member.AdministrativeName}\n{Member.Address}\n{plz.Plz} {plz.Dest}\nÖsterreich";
}
}

View File

@@ -0,0 +1,86 @@
@using RazorLight
@inherits TemplatePage<Elwig.Documents.CreditNote>
@model Elwig.Documents.CreditNote
@{ Layout = "BusinessDocument"; }
<link rel="stylesheet" href="file:///@Raw(Model.DataPath)\resources\style-creditnote.css"/>
@{
var bucketNum = Model.BucketNames.Length;
}
<main>
<div class="date">@Model.Location, am @($"{Model.Date:dd.MM.yyyy}")</div>
<h1>@Model.Title</h1>
<table class="credit">
<colgroup>
<col style="width: 24mm;"/>
<col style="width: 6mm;"/>
<col style="width: 31mm;"/>
<col style="width: 15mm;"/>
<col style="width: 8mm;"/>
<col style="width: 10mm;"/>
<col style="width: 12mm;"/>
<col style="width: 10mm;"/>
<col style="width: 12mm;"/>
<col style="width: 15mm;"/>
<col style="width: 17mm;"/>
</colgroup>
<thead>
<tr>
<th rowspan="3" style="text-align: left;">Lieferschein-Nr.</th>
<th rowspan="3">Pos.</th>
<th rowspan="3" style="text-align: left;">Sorte</th>
<th rowspan="3" style="text-align: left;">Attribut(e)</th>
<th rowspan="2" colspan="2">Gradation</th>
<th colspan="2">Zu-/Abschläge</th>
<th colspan="2">@Raw(string.Join("<br/>", Model.BucketNames))</th>
<th rowspan="2">Betrag</th>
</tr>
<tr>
<th>Abs.</th>
<th>Rel.</th>
<th>Gewicht</th>
<th>Preis</th>
</tr>
<tr>
<th>[°Oe]</th>
<th>[°KMW]</th>
<th>[@Model.CurrencySymbol/kg]</th>
<th>[%]</th>
<th>[kg]</th>
<th>[@Model.CurrencySymbol/kg]</th>
<th>[@Model.CurrencySymbol]</th>
</tr>
</thead>
<tbody>
@{
string FormatRow(int? weight, decimal? amount) {
var w = weight == null || weight == 0 ? "-" : $"{weight:N0}";
return $"<td class='weight'>{w}</td><td class='amount'>{amount?.ToString("0." + string.Concat(Enumerable.Repeat('0', Model.Precision)))}</td>";
}
string? last = null;
}
@foreach (var part in Model.Parts) {
var pmt = part.Payment;
var abs = pmt?.ModAbs == null || pmt?.ModAbs == 0 ? "-" : pmt?.ModAbs.ToString("0." + string.Concat(Enumerable.Repeat('0', Model.Precision)));
var rel = pmt?.ModRel == null || pmt?.ModRel == 0 ? "-" : $"{pmt?.ModRel * 100:0.00##}";
<tr class="first @(bucketNum <= 1 ? "last" : "") @(last != null && last != part.SortId ? "new" : "")">
<td rowspan="@bucketNum" class="lsnr">@part.Delivery.LsNr</td>
<td rowspan="@bucketNum" class="dpnr">@part.DPNr</td>
<td rowspan="@bucketNum" class="variant">@part.Variant.Name</td>
<td rowspan="@bucketNum" class="attribute">@string.Join(" / ", part.PartAttributes.Select(a => a.AttrId))</td>
<td rowspan="@bucketNum" class="oe">@($"{part.Oe:N0}")</td>
<td rowspan="@bucketNum" class="kmw">@($"{part.Kmw:N1}")</td>
<td rowspan="@bucketNum" class="abs">@abs</td>
<td rowspan="@bucketNum" class="rel">@rel</td>
@Raw(FormatRow(pmt?.Buckets?.ElementAtOrDefault(0), pmt?.Prices?.ElementAtOrDefault(0)))
<td rowspan="@bucketNum" class="amount sum">@($"{pmt?.Amount:N2}")</td>
</tr>
@for (int i = 1; i < bucketNum; i++) {
<tr class="@(i == bucketNum - 1 ? "last" : "")">
@Raw(FormatRow(pmt?.Buckets?.ElementAtOrDefault(i), pmt?.Prices?.ElementAtOrDefault(i)))
</tr>
}
last = part.SortId;
}
</tbody>
</table>
</main>

View File

@@ -0,0 +1,39 @@
using Elwig.Helpers;
using Elwig.Models;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
namespace Elwig.Documents {
public class CreditNote : BusinessDocument {
public Credit Credit;
public string? Text;
public string CurrencySymbol;
public string[] BucketNames;
public int Precision;
public IEnumerable<DeliveryPart> Parts;
public CreditNote(Credit c, AppDbContext ctx) : base($"Traubengutschrift Nr. {c.TgId} {c.Payment.Variant.Name}", c.Member) {
UseBillingAddress = true;
Credit = c;
Aside = Aside.Replace("</table>", "") +
$"<thead><tr><th colspan='2'>Gutschrift</th></tr></thead><tbody>" +
$"<tr><th>TG-Nr.</th><td>{c.TgId}</td></tr>" +
$"<tr><th>Überw. am</th><td>{c.Payment.Variant.TransferDate:dd.MM.yyyy}</td></tr>" +
$"<tr><th>Datum/Zeit</th><td>{c.ModifiedTimestamp:dd.MM.yyyy} / {c.ModifiedTimestamp:HH:mm}</td></tr>" +
$"</tbody></table>";
Text = App.Client.TextDeliveryNote;
DocumentId = $"Tr.-Gutschr. {c.TgId}";
CurrencySymbol = c.Payment.Variant.Season.Currency.Symbol ?? c.Payment.Variant.Season.Currency.Code;
BucketNames = c.Payment.Variant.BucketNames;
Precision = c.Payment.Variant.Season.Precision;
Parts = ctx.DeliveryParts.FromSql($"""
SELECT p.*
FROM v_delivery v
JOIN delivery_part p ON (p.year, p.did, p.dpnr) = (v.year, v.did, v.dpnr)
WHERE (v.year, v.mgnr) = ({c.Year}, {c.Member.MgNr})
ORDER BY sortid, LENGTH(attributes) DESC, attributes, kmw DESC, date, time, dpnr
""").ToList();
}
}}

View File

@@ -10,6 +10,7 @@ namespace Elwig.Documents {
public IEnumerable<(string, string, int, int, int)> MemberBuckets;
public DeliveryNote(Delivery d, AppDbContext ctx) : base($"Traubenübernahmeschein Nr. {d.LsNr}", d.Member) {
UseBillingAddress = true;
Delivery = d;
Aside = Aside.Replace("</table>", "") +
$"<thead><tr><th colspan='2'>Lieferung</th></tr></thead><tbody>" +

View File

@@ -18,12 +18,14 @@
<link rel="stylesheet" href="file:///@Raw(Model.DataPath)\resources\style-page.css"/>
</head>
<body>
<div class="m1"></div>
<div class="m2"></div>
<div class="m3"></div>
<div class="m1 r"></div>
<div class="m2 r"></div>
<div class="m3 r"></div>
@if (Model.ShowFoldMarks) {
<div class="m1"></div>
<div class="m2"></div>
<div class="m3"></div>
<div class="m1 r"></div>
<div class="m2 r"></div>
<div class="m3 r"></div>
}
<div class="footer-wrapper">
<div class="pre-footer">
<span class="date">@($"{Model.Date:dddd, d. MMMM yyyy}")</span>

View File

@@ -2,13 +2,13 @@ using System;
using System.Threading.Tasks;
using System.IO;
using Elwig.Helpers;
using System.Text;
namespace Elwig.Documents {
public abstract class Document : IDisposable {
private TempFile? PdfFile = null;
public bool ShowFoldMarks = App.Config.Debug;
public string DataPath;
public int CurrentNextSeason;
public string? DocumentId;
@@ -50,6 +50,8 @@ namespace Elwig.Documents {
name = "BusinessLetter";
} else if (this is DeliveryNote) {
name = "DeliveryNote";
} else if (this is CreditNote) {
name = "CreditNote";
} else {
throw new InvalidOperationException("Invalid document object");
}
@@ -63,7 +65,7 @@ namespace Elwig.Documents {
public async Task Generate() {
var pdf = new TempFile("pdf");
using (var tmpHtml = new TempFile("html")) {
await File.WriteAllTextAsync(tmpHtml.FilePath, await Render(), Encoding.UTF8);
await File.WriteAllTextAsync(tmpHtml.FilePath, await Render(), Utils.UTF8);
await Pdf.Convert(tmpHtml.FilePath, pdf.FilePath);
}
PdfFile = pdf;

View File

@@ -18,6 +18,7 @@ namespace Elwig.Documents {
await e.CompileTemplateAsync("BusinessDocument");
await e.CompileTemplateAsync("BusinessLetter");
await e.CompileTemplateAsync("DeliveryNote");
await e.CompileTemplateAsync("CreditNote");
Engine = e;
evtHandler();

View File

@@ -1,23 +1,8 @@
header, .address-wrapper, aside, main {
.address-wrapper, aside, main {
overflow: hidden;
}
header {
height: 45mm;
padding: 5mm;
position: absolute;
top: -25mm;
left: 0;
right: 0;
text-align: center;
}
header h1 {
font-size: 18pt;
margin-top: 10mm;
}
.spacing {
height: 20mm;
}

View File

@@ -0,0 +1,64 @@
table.credit {
font-size: 10pt;
}
table.credit th,
table.credit td {
padding: 0 0.25mm;
}
table.credit thead {
font-size: 8pt
}
table.credit thead th {
font-weight: normal;
font-style: italic;
vertical-align: bottom;
}
table.credit td {
vertical-align: top;
}
table.credit .oe,
table.credit .kmw {
text-align: center;
}
table.credit .dpnr {
text-align: center;
}
table.credit .amount,
table.credit .weight {
text-align: right;
}
table.credit .rel,
table.credit .abs {
text-align: center;
}
table.credit .amount.sum {
vertical-align: bottom;
padding-bottom: 1mm;
}
table.credit tbody tr:not(.first):not(.last) {
break-before: avoid;
break-after: avoid;
}
table.credit tbody tr.first td {
padding-top: 1mm;
}
table.credit tbody tr.last td {
padding-bottom: 1mm;
}
table.credit tbody tr.new {
border-top: 0.5pt solid black;
}

View File

@@ -27,6 +27,22 @@ table th {
text-align: center;
}
header {
height: 45mm;
padding: 5mm;
position: absolute;
top: -25mm;
left: 0;
right: 0;
text-align: center;
overflow: hidden;
}
header h1 {
font-size: 18pt;
margin-top: 10mm;
}
.footer-wrapper {
position: running(page-footer);
width: 165mm;

View File

@@ -7,7 +7,7 @@
<UseWPF>true</UseWPF>
<PreserveCompilationContext>true</PreserveCompilationContext>
<ApplicationIcon>elwig.ico</ApplicationIcon>
<Version>0.1.0</Version>
<Version>0.2.1</Version>
<SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages>
</PropertyGroup>

View File

@@ -44,6 +44,7 @@ namespace Elwig.Helpers {
public DbSet<DeliveryPartModifier> DeliveryPartModifiers { get; private set; }
public DbSet<PaymentVar> PaymentVariants { get; private set; }
public DbSet<PaymentMember> MemberPayments { get; private set; }
public DbSet<Credit> Credits { get; private set; }
private readonly StreamWriter? LogFile = null;
public static DateTime LastWriteTime => File.GetLastWriteTime(App.Config.DatabaseFile);

View File

@@ -1,14 +1,32 @@
using Elwig.Models;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Elwig.Helpers.Billing {
public class Transaction {
public readonly Member Member;
public readonly int AmountCent;
public readonly long AmountCent;
public readonly string Currency;
public readonly int Nr;
public Transaction(Member m, decimal amount) {
public Transaction(Member m, decimal amount, string currency, int nr) {
Member = m;
AmountCent = (int)(amount * 100);
AmountCent = (long)Math.Round(amount * 100);
Currency = currency;
Nr = nr;
}
public static IEnumerable<Transaction> FromPaymentVariant(PaymentVar variant) {
var last = variant.Season.PaymentVariants.Where(v => v.TransferDate != null).OrderBy(v => v.TransferDate).LastOrDefault();
var dict = last?.MemberPayments.ToDictionary(m => m.MgNr, m => m.Amount) ?? new();
return variant.Credits
.OrderBy(c => c.MgNr)
.Select(c => new Transaction(c.Member, c.Amount, variant.Season.CurrencyCode, c.TgNr))
.ToList();
}
public static string FormatAmountCent(long cents) => $"{cents / 100}.{cents % 100:00}";
}
}

View File

@@ -11,6 +11,9 @@ namespace Elwig.Helpers {
public bool IsMatzen => Client == Type.Matzen;
public bool IsWinzerkeller => Client == Type.Winzerkeller;
public bool IsWolkersdorf => Client == Type.Winzerkeller && App.ZwstId == "W";
public bool IsHaugsdorf => Client == Type.Winzerkeller && App.ZwstId == "H";
public bool IsSitzendorf => Client == Type.Winzerkeller && App.ZwstId == "S";
public string NameToken;
public string NameShort;

View File

@@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using IniParser;
using IniParser.Model;
@@ -9,6 +8,7 @@ namespace Elwig.Helpers {
public class Config {
private readonly string FileName;
public bool Debug;
public string DatabaseFile = App.DataPath + "database.sqlite3";
public string? DatabaseLog = null;
public string? Branch = null;
@@ -25,7 +25,7 @@ namespace Elwig.Helpers {
var parser = new FileIniDataParser();
IniData? ini = null;
try {
ini = parser.ReadFile(FileName, Encoding.UTF8);
ini = parser.ReadFile(FileName, Utils.UTF8);
} catch {}
if (ini == null || !ini.TryGetKey("database.file", out string db)) {
@@ -50,6 +50,13 @@ namespace Elwig.Helpers {
Branch = branch;
}
if (ini == null || !ini.TryGetKey("general.debug", out string debug)) {
Debug = false;
} else {
debug = debug.ToLower();
Debug = debug == "1" || debug == "true" || debug == "yes" || debug == "on";
}
ScaleList.Clear();
Scales = ScaleList;
if (ini != null) {
@@ -70,9 +77,10 @@ namespace Elwig.Helpers {
}
public void Write() {
using var file = new StreamWriter(FileName, false, Encoding.UTF8);
using var file = new StreamWriter(FileName, false, Utils.UTF8);
file.Write($"\r\n[general]\r\n");
if (Branch != null) file.Write($"branch = {Branch}\r\n");
if (Debug) file.Write("debug = true\r\n");
file.Write($"\r\n[database]\r\nfile = {DatabaseFile}\r\n");
if (DatabaseLog != null) file.Write($"log = {DatabaseLog}\r\n");
foreach (var s in ScaleList) {

View File

@@ -1,11 +1,14 @@
using Elwig.Models;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System;
namespace Elwig.Helpers.Export {
public class Bki : Csv<DeliveryPart> {
using Row = Tuple<(string?, string?, string?, string?, string, int, string, int), (string, int, string, string, string, int, string, double, double)>;
public class Bki : Csv<Row> {
private readonly string _clientData;
@@ -22,29 +25,42 @@ namespace Elwig.Helpers.Export {
_clientData = $"{c.LfbisNr};{c.NameFull};;{a1};{a2};{c.Plz};{c.Ort}";
}
public async Task ExportAsync(AppDbContext ctx, int year) {
await ExportAsync(await ctx.DeliveryParts.Where(p => p.Year == year).ToListAsync());
}
public void Export(AppDbContext ctx, int year) {
ExportAsync(ctx, year).GetAwaiter().GetResult();
}
public override string FormatRow(DeliveryPart p) {
var d = p.Delivery;
var m = d.Member;
string memberData;
if (m.BillingAddress is BillingAddr a) {
var (n1, n2) = Utils.SplitName(a.Name, m.FamilyName);
var (a1, a2) = Utils.SplitAddress(a.Address);
memberData = $"{m.LfbisNr};{n1};{n2};{a1};{a2};{a.PostalDest.AtPlz?.Plz};{a.PostalDest.AtPlz?.Ort.Name}";
} else {
var (a1, a2) = Utils.SplitAddress(m.Address);
memberData = $"{m.LfbisNr};{m.FamilyName};{m.AdministrativeName2};{a1};{a2};{m.PostalDest.AtPlz?.Plz};{m.PostalDest.AtPlz?.Ort.Name}";
public async Task ExportAsync(int year) {
using var cnx = await AppDbContext.ConnectAsync();
using var cmd = cnx.CreateCommand();
cmd.CommandText = $"""
SELECT lfbis_nr, family_name, name, billing_name, address, plz, ort, area,
date, weight, type, sortid, qualid, year, hkid, kmw, oe
FROM v_bki_delivery
WHERE year = {year}
""";
var r = await cmd.ExecuteReaderAsync();
List<Row> rows = new();
while (await r.ReadAsync()) {
rows.Add(new(
(r.IsDBNull(0) ? null : r.GetString(0), r.IsDBNull(1) ? null : r.GetString(1), r.IsDBNull(2) ? null : r.GetString(2), r.IsDBNull(3) ? null : r.GetString(3), r.GetString(4), r.GetInt32(5), r.GetString(6), r.GetInt32(7)),
(r.GetString(8), r.GetInt32(9), r.GetString(10), r.GetString(11), r.GetString(12), r.GetInt32(13), r.GetString(14), r.GetDouble(15), r.GetDouble(16))
));
}
var s = p.Variant;
var deliveryData = $"{d.Date:dd.MM.yyyy};{p.Weight};TB;{(s.IsWhite ? "J" : "")};{(s.IsRed ? "J" : "")};{s.SortId};;;{p.QualId};{d.Year};{p.HkId};{p.Kmw};{p.Oe}";
var vollData = $"N;;;{m.AreaCommitments.Where(a => a.YearFrom <= d.Year && (a.YearTo == null || a.YearTo >= d.Year)).Sum(a => a.Area) / 10_000.0}";
await ExportAsync(rows);
}
public void Export(int year) {
ExportAsync(year).GetAwaiter().GetResult();
}
public override string FormatRow(Row row) {
var (member, delivery) = row;
var (lfBisNr, familyName, name, billingName, address, plz, ort, area) = member;
var (date, weight, type, sortid, qualid, year, hkid, kmw, oe) = delivery;
var (n1, n2) = billingName == null ? (familyName, name) : Utils.SplitName(billingName, familyName);
var (a1, a2) = Utils.SplitAddress(address);
var memberData = $"{lfBisNr};{n1};{n2};{a1};{a2};{plz};{ort}";
var deliveryData = $"{string.Join(".", date.Split("-").Reverse())};{weight};TB;{(type == "W" ? "J" : "")};{(type == "R" ? "J" : "")};{sortid};;;{qualid};{year};{hkid};{kmw:0.0};{oe:0}";
var vollData = $"N;;;{area / 10_000.0}";
return $"{_clientData};{memberData};{deliveryData};{vollData}";
}
}

View File

@@ -2,43 +2,54 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Elwig.Helpers.Export {
public abstract class Csv<T> : IExporter<T> {
public static string FileExtension => "csv";
protected readonly StreamWriter Writer;
private readonly StreamWriter _writer;
protected readonly char Separator;
protected string? Header;
public Csv(string filename, char separator = ';') : this(filename, separator, Encoding.UTF8) { }
public Csv(string filename, char separator = ';') : this(filename, separator, Utils.UTF8) { }
public Csv(string filename, char separator, Encoding encoding) {
Writer = new StreamWriter(filename, false, encoding);
_writer = new StreamWriter(filename, false, encoding);
Separator = separator;
}
public void Dispose() {
GC.SuppressFinalize(this);
Writer.Dispose();
_writer.Dispose();
}
public ValueTask DisposeAsync() {
GC.SuppressFinalize(this);
return Writer.DisposeAsync();
return _writer.DisposeAsync();
}
public async Task ExportAsync(IEnumerable<T> data) {
if (Header != null) await Writer.WriteLineAsync(Header);
public async Task ExportAsync(IEnumerable<T> data, IProgress<double>? progress = null) {
progress?.Report(0.0);
int count = data.Count() + 2, i = 0;
if (Header != null) await _writer.WriteLineAsync(Header);
progress?.Report(100.0 * ++i / count);
foreach (var row in data) {
await Writer.WriteLineAsync(FormatRow(row));
await _writer.WriteLineAsync(FormatRow(row));
progress?.Report(100.0 * ++i / count);
}
await _writer.FlushAsync();
progress?.Report(100.0);
}
public void Export(IEnumerable<T> data) {
ExportAsync(data).GetAwaiter().GetResult();
public void Export(IEnumerable<T> data, IProgress<double>? progress = null) {
ExportAsync(data, progress).GetAwaiter().GetResult();
}
public string FormatRow(IEnumerable row) {

View File

@@ -1,6 +1,9 @@
using Elwig.Helpers.Billing;
using Elwig.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace Elwig.Helpers.Export {
@@ -8,20 +11,99 @@ namespace Elwig.Helpers.Export {
public static string FileExtension => "xml";
private readonly StreamWriter _writer;
private readonly DateOnly _date;
private readonly int _year;
private readonly string _name;
private readonly int _nr;
public Ebics(PaymentVar variant, string filename) {
_writer = new(filename, false, Utils.UTF8);
_date = variant.TransferDate ?? DateOnly.Parse("2021-01-10"); //throw new ArgumentException("TransferDate has to be set in PaymentVar");
_year = variant.Year;
_name = variant.Name;
_nr = variant.AvNr;
}
public void Dispose() {
throw new NotImplementedException();
GC.SuppressFinalize(this);
_writer.Dispose();
}
public ValueTask DisposeAsync() {
throw new NotImplementedException();
GC.SuppressFinalize(this);
return _writer.DisposeAsync();
}
public void Export(IEnumerable<Transaction> data) {
throw new NotImplementedException();
public void Export(IEnumerable<Transaction> transactions, IProgress<double>? progress = null) {
ExportAsync(transactions, progress).GetAwaiter().GetResult();
}
public Task ExportAsync(IEnumerable<Transaction> data) {
throw new NotImplementedException();
public async Task ExportAsync(IEnumerable<Transaction> transactions, IProgress<double>? progress = null) {
progress?.Report(0.0);
var nbOfTxs = transactions.Count();
int count = nbOfTxs + 2, i = 0;
var ctrlSum = Transaction.FormatAmountCent(transactions.Sum(tx => tx.AmountCent));
var msgId = $"ELWIG-{App.Client.NameToken}-{_year}-AV{_nr:00}";
var pmtInfId = $"{msgId}-1";
await _writer.WriteLineAsync($"""
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09 pain.001.001.09.xsd">
<CstmrCdtTrfInitn>
<GrpHdr>
<MsgId>{msgId}</MsgId>
<CreDtTm>{DateTime.UtcNow:o}</CreDtTm>
<NbOfTxs>{nbOfTxs}</NbOfTxs>
<CtrlSum>{ctrlSum}</CtrlSum>
<InitgPty><Nm>{App.Client.NameFull}</Nm></InitgPty>
</GrpHdr>
<PmtInf>
<PmtInfId>{pmtInfId}</PmtInfId>
<PmtMtd>TRF</PmtMtd>
<NbOfTxs>{nbOfTxs}</NbOfTxs>
<CtrlSum>{ctrlSum}</CtrlSum>
<ReqdExctnDt><Dt>{_date:yyyy-MM-dd}</Dt></ReqdExctnDt>
<Dbtr><Nm>{App.Client.NameFull}</Nm></Dbtr>
<DbtrAcct><Id><IBAN>{App.Client.Iban?.Replace(" ", "")}</IBAN></Id></DbtrAcct>
<DbtrAgt><FinInstnId><BICFI>{App.Client.Bic ?? "NOTPROVIDED"}</BICFI></FinInstnId></DbtrAgt>
""");
progress?.Report(100.0 * ++i / count);
foreach (var tx in transactions) {
var a = (IAddress?)tx.Member.BillingAddress ?? tx.Member;
var (a1, a2) = Utils.SplitAddress(a.Address);
var id = $"ELWIG-{App.Client.NameToken}-{_year}-TG{tx.Nr:0000}";
var info = $"{_name} - Traubengutschrift {_year}/{tx.Nr:000}";
await _writer.WriteLineAsync($"""
<CdtTrfTxInf>
<PmtId><EndToEndId>{id}</EndToEndId></PmtId>
<Amt><InstdAmt Ccy="{tx.Currency}">{Transaction.FormatAmountCent(tx.AmountCent)}</InstdAmt></Amt>
<Cdtr>
<Nm>{a.Name}</Nm>
<PstlAdr>
<StrtNm>{a1}</StrtNm><BldgNb>{a2}</BldgNb>
<PstCd>{a.PostalDest.AtPlz?.Plz}</PstCd><TwnNm>{a.PostalDest.AtPlz?.Ort.Name}</TwnNm>
<Ctry>{a.PostalDest.Country.Alpha2}</Ctry>
</PstlAdr>
</Cdtr>
<CdtrAcct><Id><IBAN>{tx.Member.Iban}</IBAN></Id><CdtrAcct>
<CdtrAgt><FinInstnId><BICFI>{tx.Member.Bic ?? "NOTPROVIDED"}</BICFI></FinInstnId></CdtrAgt>
<RmtInf><Ustrd>{info}</Ustrd></RmtInf>
</CdtTrfTxInf>
""");
progress?.Report(100.0 * ++i / count);
}
await _writer.WriteLineAsync("""
</PmtInf>
</CstmrCdtTrfInitn>
</Document>
""");
await _writer.FlushAsync();
progress?.Report(100.0);
}
}
}

View File

@@ -7,18 +7,20 @@ namespace Elwig.Helpers.Export {
/// <summary>
/// The default file extension of the exported files to be used (whithout a preceding ".")
/// </summary>
static string FileExtension { get; }
static abstract string FileExtension { get; }
/// <summary>
/// Export the given data to the given file.
/// </summary>
/// <param name="data">The data to be exported</param>
void Export(IEnumerable<T> data);
/// <param name="progress">The progress object to report to</param>
void Export(IEnumerable<T> data, IProgress<double>? progress = null);
/// <summary>
/// Export the given data to the given file.
/// Asynchronosly export the given data to the given file.
/// </summary>
/// <param name="data">The data to be exported</param>
Task ExportAsync(IEnumerable<T> data);
/// <param name="progress">The progress object to report to</param>
Task ExportAsync(IEnumerable<T> data, IProgress<double>? progress = null);
}
}

View File

@@ -0,0 +1,9 @@
using Elwig.Models;
namespace Elwig.Helpers {
public interface IAddress {
string Name { get; }
string Address { get; }
PostalDest PostalDest { get; }
}
}

View File

@@ -15,6 +15,8 @@ using Elwig.Models;
namespace Elwig.Helpers {
public static partial class Utils {
public static readonly Encoding UTF8 = new UTF8Encoding(false, true);
public static int CurrentYear => DateTime.Now.Year;
public static int CurrentNextSeason => DateTime.Now.Year - (DateTime.Now.Month <= 3 ? 1 : 0);
public static int CurrentLastSeason => DateTime.Now.Year - (DateTime.Now.Month <= 7 ? 1 : 0);
@@ -217,8 +219,8 @@ namespace Elwig.Helpers {
.Sum();
}
public static (int, string?)? ShowManualWeighingDialog() {
var d = new ManualWeighingDialog();
public static (int, string?)? ShowManualWeighingDialog(string? reason = null) {
var d = new ManualWeighingDialog(reason);
return d.ShowDialog() == true ? (d.Weight, d.Reason) : null;
}
@@ -303,7 +305,7 @@ namespace Elwig.Helpers {
}
public static (string, string?) SplitName(string fullName, string? familyName) {
if (familyName == null) return (fullName, null);
if (familyName == null || familyName == "") return (fullName, null);
var p0 = fullName.ToLower().IndexOf(familyName.ToLower());
if (p0 == -1) return (fullName, null);
var p1 = fullName.IndexOf(" und ");

View File

@@ -0,0 +1,44 @@
using System;
using System.Threading.Tasks;
namespace Elwig.Helpers.Weighing {
public class InvalidScale : IScale {
public string Manufacturer => "NONE";
public string Model => "NONE";
public string ScaleId { get; private set; }
public int InternalScaleNr => 0;
public bool IsReady => false;
public bool HasFillingClearance => false;
public int? WeightLimit => null;
public string? LogPath => null;
public InvalidScale(string id) {
ScaleId = id;
}
public void Dispose() {
GC.SuppressFinalize(this);
}
public Task<WeighingResult> Weigh() {
throw new NotImplementedException();
}
public Task<WeighingResult> GetCurrentWeight() {
throw new NotImplementedException();
}
public Task Empty() {
throw new NotImplementedException();
}
public Task GrantFillingClearance() {
throw new NotImplementedException();
}
public Task RevokeFillingClearance() {
throw new NotImplementedException();
}
}
}

View File

@@ -1,9 +1,10 @@
using Elwig.Helpers;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations.Schema;
namespace Elwig.Models {
[Table("member_billing_address"), PrimaryKey("MgNr")]
public class BillingAddr {
public class BillingAddr : IAddress {
[Column("mgnr")]
public int MgNr { get; set; }

104
Elwig/Models/Credit.cs Normal file
View File

@@ -0,0 +1,104 @@
using Elwig.Helpers;
using Microsoft.EntityFrameworkCore;
using System;
using System.ComponentModel.DataAnnotations.Schema;
namespace Elwig.Models {
[Table("credit"), PrimaryKey("Year", "TgNr"), Index("Year", "AvNr", "MgNr", IsUnique = true)]
public class Credit {
[Column("year")]
public int Year { get; set; }
[Column("tgnr")]
public int TgNr { get; set; }
[NotMapped]
public string TgId => $"{Year}/{TgNr:000}";
[Column("mgnr")]
public int MgNr { get; set; }
[Column("avnr")]
public int AvNr { get; set; }
[Column("net_amount")]
public long NetAmountValue { get; set; }
[NotMapped]
public decimal NetAmount {
get => Utils.DecFromDb(NetAmountValue, 2);
set => NetAmountValue = Utils.DecToDb(value, 2);
}
[Column("prev_net_amount")]
public long? PrevNetAmountValue { get; set; }
[NotMapped]
public decimal? PrevNetAmount {
get => PrevNetAmountValue != null ? Utils.DecFromDb(PrevNetAmountValue.Value, 2) : null;
set => PrevNetAmountValue = value != null ? Utils.DecToDb(value.Value, 2) : null;
}
[Column("vat")]
public double VatValue { get; set; }
[NotMapped]
public decimal Vat {
get => (decimal)VatValue;
set => VatValue = (double)value;
}
[Column("vat_amount")]
public long VatAmountValue { get; private set; }
[NotMapped]
public decimal VatAmount {
get => Utils.DecFromDb(VatAmountValue, 2);
}
[Column("gross_amount")]
public long GrossAmountValue { get; private set; }
[NotMapped]
public decimal GrossAmount {
get => Utils.DecFromDb(GrossAmountValue, 2);
}
[Column("modifiers")]
public long? ModifiersValue { get; set; }
[NotMapped]
public decimal? Modifiers {
get => ModifiersValue != null ? Utils.DecFromDb(ModifiersValue.Value, 2) : null;
set => ModifiersValue = value != null ? Utils.DecToDb(value.Value, 2) : null;
}
[Column("prev_modifiers")]
public long? PrevModifiersValue { get; set; }
[NotMapped]
public decimal? PrevModifiers {
get => PrevModifiersValue != null ? Utils.DecFromDb(PrevModifiersValue.Value, 2) : null;
set => PrevModifiersValue = value != null ? Utils.DecToDb(value.Value, 2) : null;
}
[Column("amount")]
public long AmountValue { get; private set; }
[NotMapped]
public decimal Amount {
get => Utils.DecFromDb(AmountValue, 2);
}
[Column("ctime")]
public long CTime { get; private set; }
[NotMapped]
public DateTime CreatedTimestamp => DateTimeOffset.FromUnixTimeSeconds(CTime).LocalDateTime;
[Column("mtime")]
public long MTime { get; private set; }
[NotMapped]
public DateTime ModifiedTimestamp => DateTimeOffset.FromUnixTimeSeconds(CTime).LocalDateTime;
[ForeignKey("Year, AvNr, MgNr")]
public virtual PaymentMember Payment { get; private set; }
[ForeignKey("Year, AvNr")]
public virtual PaymentVar Variant { get; private set; }
[ForeignKey("MgNr")]
public virtual Member Member { get; private set; }
}
}

View File

@@ -30,15 +30,10 @@ namespace Elwig.Models {
[Column("kmw")]
public double Kmw { get; set; }
[NotMapped]
public double Oe {
get {
return Utils.KmwToOe(Kmw);
}
set {
Kmw = Utils.OeToKmw(value);
}
get => Utils.KmwToOe(Kmw);
set => Kmw = Utils.OeToKmw(value);
}
[Column("qualid")]
@@ -107,6 +102,10 @@ namespace Elwig.Models {
[NotMapped]
public IEnumerable<Modifier> Modifiers => PartModifiers.Select(m => m.Modifier).OrderBy(m => m.Ordering);
[InverseProperty("DeliveryPart")]
public virtual PaymentDeliveryPart? Payment { get; private set; }
[NotMapped]
public string OriginString => Origin.OriginString + "\n" + (Kg?.Gl != null ? $" / {Kg.Gl.Name}" : "") + (Kg != null ? $" / {Kg.AtKg.Gem.Name} / KG {Kg.AtKg.Name}" : "") + (Rd != null ? $" / Ried {Rd.Name}" : "");
}
}

View File

@@ -7,7 +7,7 @@ using System.Linq;
namespace Elwig.Models {
[Table("member"), PrimaryKey("MgNr")]
public class Member {
public class Member : IAddress {
[Column("mgnr")]
public int MgNr { get; set; }

View File

@@ -0,0 +1,158 @@
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
namespace Elwig.Models {
[Table("payment_delivery_part"), PrimaryKey("Year", "DId", "DPNr", "AvNr")]
public class PaymentDeliveryPart {
[Column("year")]
public int Year { get; set; }
[Column("did")]
public int DId { get; set; }
[Column("dpnr")]
public int DPNr { get; set; }
[Column("avnr")]
public int AvNr { get; set; }
[Column("mod_abs")]
public long ModAbsValue { get; set; }
[NotMapped]
public decimal ModAbs {
get => Variant.Season.DecFromDb(ModAbsValue);
set => ModAbsValue = Variant.Season.DecToDb(value);
}
[Column("mod_rel")]
public double ModRelValue { get; set; }
[NotMapped]
public decimal ModRel {
get => (decimal)ModRelValue;
set => ModRelValue = (double)value;
}
[Column("bucket_1")]
public int? Bucket1 { get; set; }
[Column("bucket_2")]
public int? Bucket2 { get; set; }
[Column("bucket_3")]
public int? Bucket3 { get; set; }
[Column("bucket_4")]
public int? Bucket4 { get; set; }
[Column("bucket_5")]
public int? Bucket5 { get; set; }
[Column("bucket_6")]
public int? Bucket6 { get; set; }
[Column("bucket_7")]
public int? Bucket7 { get; set; }
[Column("bucket_8")]
public int? Bucket8 { get; set; }
[Column("bucket_9")]
public int? Bucket9 { get; set; }
[NotMapped]
public int[] Buckets => (new int?[] { Bucket1, Bucket2, Bucket3, Bucket4, Bucket5, Bucket6, Bucket7, Bucket8, Bucket9 })
.Where(b => b != null).Select(b => b.Value).ToArray();
[Column("price_1")]
public long? Price1Value { get; set; }
[NotMapped]
public decimal? Price1 {
get => Price1Value != null ? Variant.Season.DecFromDb(Price1Value.Value) : null;
set => Price1Value = value != null ? Variant.Season.DecToDb(value.Value) : null;
}
[Column("price_2")]
public long? Price2Value { get; set; }
[NotMapped]
public decimal? Price2 {
get => Price2Value != null ? Variant.Season.DecFromDb(Price2Value.Value) : null;
set => Price2Value = value != null ? Variant.Season.DecToDb(value.Value) : null;
}
[Column("price_3")]
public long? Price3Value { get; set; }
[NotMapped]
public decimal? Price3 {
get => Price3Value != null ? Variant.Season.DecFromDb(Price3Value.Value) : null;
set => Price3Value = value != null ? Variant.Season.DecToDb(value.Value) : null;
}
[Column("price_4")]
public long? Price4Value { get; set; }
[NotMapped]
public decimal? Price4 {
get => Price4Value != null ? Variant.Season.DecFromDb(Price4Value.Value) : null;
set => Price4Value = value != null ? Variant.Season.DecToDb(value.Value) : null;
}
[Column("price_5")]
public long? Price5Value { get; set; }
[NotMapped]
public decimal? Price5 {
get => Price5Value != null ? Variant.Season.DecFromDb(Price5Value.Value) : null;
set => Price5Value = value != null ? Variant.Season.DecToDb(value.Value) : null;
}
[Column("price_6")]
public long? Price6Value { get; set; }
[NotMapped]
public decimal? Price6 {
get => Price6Value != null ? Variant.Season.DecFromDb(Price6Value.Value) : null;
set => Price6Value = value != null ? Variant.Season.DecToDb(value.Value) : null;
}
[Column("price_7")]
public long? Price7Value { get; set; }
[NotMapped]
public decimal? Price7 {
get => Price7Value != null ? Variant.Season.DecFromDb(Price7Value.Value) : null;
set => Price7Value = value != null ? Variant.Season.DecToDb(value.Value) : null;
}
[Column("price_8")]
public long? Price8Value { get; set; }
[NotMapped]
public decimal? Price8 {
get => Price8Value != null ? Variant.Season.DecFromDb(Price8Value.Value) : null;
set => Price8Value = value != null ? Variant.Season.DecToDb(value.Value) : null;
}
[Column("price_9")]
public long? Price9Value { get; set; }
[NotMapped]
public decimal? Price9 {
get => Price9Value != null ? Variant.Season.DecFromDb(Price9Value.Value) : null;
set => Price9Value = value != null ? Variant.Season.DecToDb(value.Value) : null;
}
[Column("amount")]
public long? AmountValue { get; set; }
[NotMapped]
public decimal? Amount {
get => AmountValue != null ? Variant.Season.DecFromDb(AmountValue.Value) : null;
set => AmountValue = value != null ? Variant.Season.DecToDb(value.Value) : null;
}
[NotMapped]
public decimal[] Prices => (new decimal?[] { Price1, Price2, Price3, Price4, Price5, Price6, Price7, Price8, Price9 })
.Where(p => p != null).Select(p => p.Value).ToArray();
[ForeignKey("Year, AvNr")]
public virtual PaymentVar Variant { get; private set; }
[ForeignKey("Year, DId, DPNr")]
public virtual DeliveryPart DeliveryPart { get; private set; }
}
}

View File

@@ -27,5 +27,8 @@ namespace Elwig.Models {
[ForeignKey("MgNr")]
public virtual Member Member { get; private set; }
[InverseProperty("Payment")]
public virtual Credit? Credit { get; private set; }
}
}

View File

@@ -1,6 +1,8 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
namespace Elwig.Models {
[Table("payment_variant"), PrimaryKey("Year", "AvNr")]
@@ -19,12 +21,17 @@ namespace Elwig.Models {
[NotMapped]
public DateOnly Date {
get {
return DateOnly.ParseExact(DateString, "yyyy-MM-dd");
}
set {
DateString = value.ToString("yyyy-MM-dd");
}
get => DateOnly.ParseExact(DateString, "yyyy-MM-dd");
set => DateString = value.ToString("yyyy-MM-dd");
}
[Column("transfer_date")]
public string? TransferDateString { get; set; }
[NotMapped]
public DateOnly? TransferDate {
get => TransferDateString != null ? DateOnly.ParseExact(TransferDateString, "yyyy-MM-dd") : null;
set => TransferDateString = value?.ToString("yyyy-MM-dd");
}
[Column("test_variant")]
@@ -60,6 +67,10 @@ namespace Elwig.Models {
[Column("bucket_9_name")]
public string? Bucket9Name { get; set; }
[NotMapped]
public string[] BucketNames => (new string?[] { Bucket1Name, Bucket2Name, Bucket3Name, Bucket4Name, Bucket5Name, Bucket6Name, Bucket7Name, Bucket8Name, Bucket9Name })
.Where(n => n != null).Select(n => n ?? "").ToArray();
[Column("comment")]
public string? Comment { get; set; }
@@ -68,5 +79,11 @@ namespace Elwig.Models {
[ForeignKey("Year")]
public virtual Season Season { get; private set; }
[InverseProperty("Variant")]
public virtual ISet<PaymentMember> MemberPayments { get; private set; }
[InverseProperty("Variant")]
public virtual ISet<Credit> Credits { get; private set; }
}
}

View File

@@ -48,6 +48,12 @@ namespace Elwig.Models {
[InverseProperty("Season")]
public virtual ISet<Modifier> Modifiers { get; private set; }
[InverseProperty("Season")]
public virtual ISet<PaymentVar> PaymentVariants { get; private set; }
[InverseProperty("Season")]
public virtual ISet<Delivery> Deliveries { get; private set; }
public decimal DecFromDb(long value) {
return Utils.DecFromDb(value, Precision);
}

View File

@@ -32,6 +32,7 @@ namespace Elwig.Windows {
LockContext = IsEditing;
}
}
protected bool DoShowWarningWindows = true;
protected bool IsClosing { get; private set; }
private TextBox[] TextBoxInputs;
@@ -81,6 +82,14 @@ namespace Elwig.Windows {
}
private void OnClosing(object? sender, CancelEventArgs evt) {
if ((IsCreating || IsEditing) && HasChanged) {
var r = System.Windows.MessageBox.Show("Soll das Fenster wirklich geschlossen werden?", "Schlie<69>en best<73>tigen",
MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
if (r != MessageBoxResult.Yes) {
evt.Cancel = true;
return;
}
}
IsClosing = true;
}
@@ -292,12 +301,20 @@ namespace Elwig.Windows {
}
protected bool HasChanged =>
!IsValid ||
TextBoxInputs.Any(InputHasChanged) ||
ComboBoxInputs.Any(InputHasChanged) ||
CheckComboBoxInputs.Any(InputHasChanged) ||
CheckBoxInputs.Any(InputHasChanged) ||
RadioButtonInputs.Any(InputHasChanged);
IsEditing && (
!IsValid ||
TextBoxInputs.Any(InputHasChanged) ||
ComboBoxInputs.Any(InputHasChanged) ||
CheckComboBoxInputs.Any(InputHasChanged) ||
CheckBoxInputs.Any(InputHasChanged) ||
RadioButtonInputs.Any(InputHasChanged)
) || IsCreating && (
TextBoxInputs.Any(i => InputIsNotDefault(i) || (!i.IsReadOnly && i.Text != "")) ||
ComboBoxInputs.Any(i => InputIsNotDefault(i) || (i.IsEnabled && i.SelectedItem != null)) ||
CheckComboBoxInputs.Any(i => InputIsNotDefault(i) || i.SelectedItem != null) ||
CheckBoxInputs.Any(InputIsNotDefault) ||
RadioButtonInputs.Any(InputIsNotDefault)
);
protected void UpdatePlz(TextBox plzInput, ComboBox ortInput) {
var plzInputValid = GetInputValid(plzInput);
@@ -363,7 +380,7 @@ namespace Elwig.Windows {
}
protected bool InputLostFocus(TextBox input, ValidationResult res, string? msg = null) {
if (!res.IsValid && !IsClosing && (IsEditing || IsCreating))
if (DoShowWarningWindows && !res.IsValid && !IsClosing && (IsEditing || IsCreating))
System.Windows.MessageBox.Show(res.ErrorContent.ToString(), msg ?? res.ErrorContent.ToString(), MessageBoxButton.OK, MessageBoxImage.Warning);
return res.IsValid;
}
@@ -396,7 +413,7 @@ namespace Elwig.Windows {
UpdateButtons();
}
protected void TextBox_TextChanged(object sender, RoutedEventArgs evt) {
protected void TextBox_TextChanged(object sender, RoutedEventArgs? evt) {
var input = (TextBox)sender;
if (SenderIsRequired(input) && input.Text.Length == 0) {
ValidateInput(input, false);

View File

@@ -6,7 +6,7 @@
xmlns:local="clr-namespace:Elwig.Windows"
mc:Ignorable="d"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Title="Flächenbindugen - Elwig" Height="480" Width="850"
Title="Flächenbindungen - Elwig" Height="480" Width="850"
Loaded="Window_Loaded">
<Window.Resources>
<Style TargetType="Label">

View File

@@ -5,7 +5,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Elwig.Windows"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Title="Lieferungsverwaltung - Elwig" Height="720" Width="1100" MinHeight="700" MinWidth="1000"
Title="Lieferungen - Elwig" Height="720" Width="1100" MinHeight="700" MinWidth="1000"
Loaded="Window_Loaded">
<Window.Resources>
<Style TargetType="Label">
@@ -65,8 +65,7 @@
Click="Menu_Print_PrintDeliveryNote_Click"/>
</MenuItem>
<MenuItem Header="Exportieren">
<MenuItem x:Name="Menu_Export_Bki" Header="Traubentransportscheinliste (BKI)"
Click="Menu_Export_Bki_Click"/>
<MenuItem x:Name="Menu_Export_Bki" Header="Traubentransportscheinliste (BKI)"/>
</MenuItem>
<MenuItem Header="Werkzeuge">
<MenuItem Header="Alle Lieferscheine überprüfen"/>
@@ -161,10 +160,10 @@
<Label Content="Mitglied:" Margin="10,10,0,0" Grid.Column="0"/>
<TextBox x:Name="MgNrInput" Width="48" Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" HorizontalAlignment="Left" TextAlignment="Right"
TextChanged="MgNrInput_TextChanged" LostFocus="MgNrInput_LostFocus"/>
TextChanged="MgNrInput_TextChanged" LostFocus="MgNrInput_LostFocus" KeyUp="Input_KeyUp"/>
<ComboBox x:Name="MemberInput" Grid.Column="1" Margin="53,10,10,10" IsEditable="True"
ItemTemplate="{StaticResource MemberAdminNameTemplate}" TextSearch.TextPath="AdministrativeName"
SelectionChanged="MemberInput_SelectionChanged"/>
SelectionChanged="MemberInput_SelectionChanged" KeyUp="Input_KeyUp"/>
<Label Content="Wohnort:" Margin="10,38,0,0" Grid.Column="0"/>
<TextBox x:Name="MemberAddressField" Grid.Column="1" Margin="0,40,10,10" FontSize="12" Height="22"
@@ -210,15 +209,15 @@
<Label Content="Sorte:" Margin="10,10,0,0" Grid.Column="0"/>
<TextBox x:Name="SortIdInput" Width="36" Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" HorizontalAlignment="Left"
TextChanged="SortIdInput_TextChanged" LostFocus="SortIdInput_LostFocus"/>
TextChanged="SortIdInput_TextChanged" LostFocus="SortIdInput_LostFocus" KeyUp="Input_KeyUp"/>
<ComboBox x:Name="WineVarietyInput" Grid.Row="1" Grid.Column="1" Margin="41,10,10,10"
ItemTemplate="{StaticResource WineVarietyTemplate}" TextSearch.TextPath="Name"
SelectionChanged="WineVarietyInput_SelectionChanged"/>
SelectionChanged="WineVarietyInput_SelectionChanged" KeyUp="Input_KeyUp"/>
<Label Content="Attribute:" Margin="10,40,0,0" Grid.Column="0"/>
<xctk:CheckComboBox x:Name="AttributesInput" Grid.Row="1" Grid.Column="1" Margin="0,40,10,10"
DisplayMemberPath="Name" Delimiter=", " AllItemsSelectedContent="Alle"
ItemSelectionChanged="AttributesInput_SelectionChanged"/>
ItemSelectionChanged="AttributesInput_SelectionChanged" KeyUp="Input_KeyUp"/>
</Grid>
</GroupBox>
@@ -247,7 +246,7 @@
SelectionChanged="WineQualityLevelInput_SelectionChanged"/>
<CheckBox x:Name="AbgewertetInput" Content="Abgewertet" IsEnabled="False"
VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0,75,10,10" Grid.Column="1"/>
VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,75,10,10" Grid.Column="0" Grid.ColumnSpan="2"/>
</Grid>
</GroupBox>

View File

@@ -1,8 +1,10 @@
using Elwig.Documents;
using Elwig.Helpers;
using Elwig.Helpers.Export;
using Elwig.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -23,6 +25,7 @@ namespace Elwig.Windows {
private List<string> TextFilter = new();
private readonly RoutedCommand CtrlF = new();
private string? LastScaleError = null;
private string? ManualWeighingReason = null;
private string? ScaleId = null;
private string? WeighingId = null;
@@ -58,6 +61,8 @@ namespace Elwig.Windows {
SearchInput.TextChanged -= SearchInput_TextChanged;
SeasonInput.Value = Utils.CurrentLastSeason;
DoShowWarningWindows = false;
if (IsReceipt) {
Title = "Übernahme - Elwig";
TodayOnlyInput.IsChecked = true;
@@ -87,13 +92,13 @@ namespace Elwig.Windows {
AllSeasonsInput.IsChecked = true;
}
private async void Window_Loaded(object sender, RoutedEventArgs evt) {
private void Window_Loaded(object sender, RoutedEventArgs evt) {
OnSecondPassed(null, null);
Timer.Start();
LockInputs();
if (IsReceipt) {
NewDeliveryButton_Click(null, null);
if ((await Context.Seasons.FindAsync(Utils.CurrentYear)) == null) {
if ((Context.Seasons.Find(Utils.CurrentYear)) == null) {
MessageBox.Show("Die Saison für das aktuelle Jahr wurde noch nicht erstellt. Neue Lieferungen können nicht abgespeichert werden.",
"Saison noch nicht erstellt", MessageBoxButton.OK, MessageBoxImage.Error);
}
@@ -118,8 +123,20 @@ namespace Elwig.Windows {
await doc.Print();
}
private void Menu_Export_Bki_Click(object sender, RoutedEventArgs evt) {
// TODO export Traubentransportscheinliste
private async void Menu_Export_Bki_Click(object sender, RoutedEventArgs evt) {
if (sender is not MenuItem m) return;
var year = int.Parse(m.Header.ToString()?.Split(" ")[^1] ?? Utils.CurrentLastSeason.ToString());
var d = new SaveFileDialog() {
FileName = $"{App.Client.NameToken}-Traubentransportscheinliste-{year}",
DefaultExt = Bki.FileExtension,
Title = $"Traubentransportscheinliste (BKI) speichern unter - Elwig"
};
if (d.ShowDialog() == true) {
Mouse.OverrideCursor = Cursors.Wait;
using var file = new Bki(d.FileName);
await file.ExportAsync(year);
Mouse.OverrideCursor = null;
}
}
private void OnSecondPassed(object? sender, EventArgs? evt) {
@@ -131,11 +148,16 @@ namespace Elwig.Windows {
}
private void InitialInputs() {
LastScaleError = null;
WeighingId = null;
ScaleId = null;
ManualWeighingReason = null;
ClearOriginalValues();
ClearDefaultValues();
HandPickedInput.IsChecked = null;
if (App.Client.IsMatzen) {
if (App.Client.IsMatzen || App.Client.IsWolkersdorf) {
GerebeltGewogenInput.IsChecked = true;
GerebeltGewogenInput.IsEnabled = false;
SetDefaultValue(GerebeltGewogenInput);
@@ -145,6 +167,8 @@ namespace Elwig.Windows {
UnsetDefaultValue(GerebeltGewogenInput);
}
WineQualityLevelInput.IsEnabled = false;
SetDefaultValue(HandPickedInput);
ValidateRequiredInputs();
}
@@ -161,11 +185,21 @@ namespace Elwig.Windows {
bool ch = HasChanged, v = IsValid;
ResetButton.IsEnabled = ch;
SaveButton.IsEnabled = v && ch;
FinishButton.IsEnabled = v || !ch;
NewDeliveryPartButton.IsEnabled = v;
FinishButton.IsEnabled = v && ch;
NewDeliveryPartButton.IsEnabled = v && ch;
CancelCreatingButton.IsEnabled = DeliveryList.SelectedItem == null || DeliveryPartList.SelectedItem == null;
}
private void Input_KeyUp(object sender, KeyEventArgs evt) {
if (sender is not Control ctrl) return;
if (evt.Key != Key.Enter) return;
if (ctrl == MgNrInput || ctrl == MemberInput) {
SortIdInput.Focus(); SortIdInput.SelectAll();
} else if (ctrl == SortIdInput || ctrl == WineVarietyInput || ctrl == AttributesInput) {
GradationOeInput.Focus(); GradationOeInput.SelectAll();
}
}
private async Task RefreshDeliveryList() {
await RefreshDeliveryListQuery();
}
@@ -198,6 +232,7 @@ namespace Elwig.Windows {
double filterOeLt = 0;
var filter = TextFilter.ToList();
var hasFilters = filter.Count > 0;
if (filter.Count > 0) {
var var = await Context.WineVarieties.Select(v => v.SortId).ToListAsync();
var qual = await Context.WineQualityLevels.Select(q => q.QualId).ToListAsync();
@@ -303,7 +338,8 @@ namespace Elwig.Windows {
.ToList();
}
ControlUtils.RenewItemsSource(DeliveryList, deliveries, d => ((d as Delivery)?.Year, (d as Delivery)?.DId), DeliveryList_SelectionChanged, ControlUtils.RenewSourceDefault.IfOnly, !updateSort);
ControlUtils.RenewItemsSource(DeliveryList, deliveries, d => ((d as Delivery)?.Year, (d as Delivery)?.DId),
DeliveryList_SelectionChanged, hasFilters ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
var members = deliveries.Select(d => d.Member).DistinctBy(m => m.MgNr).ToList();
StatusMembers.Text = $"Mitglieder: {members.Count}" + (members.Count > 0 && members.Count <= 4 ? $" ({string.Join(", ", members.Select(m => m.AdministrativeName))})" : "");
@@ -386,10 +422,19 @@ namespace Elwig.Windows {
Title = $"Lieferungen - {Member.AdministrativeName} - Elwig";
}
Menu_Export_Bki.Items.Clear();
foreach (var s in await Context.Seasons.OrderByDescending(s => s.Year).ToListAsync()) {
var i = new MenuItem {
Header = $"Season {s.Year}",
};
i.Click += Menu_Export_Bki_Click;
Menu_Export_Bki.Items.Add(i);
}
await RefreshDeliveryList();
var d = DeliveryList.SelectedItem as Delivery;
var y = d?.Year ?? Utils.CurrentLastSeason;
ControlUtils.RenewItemsSource(MemberInput, await Context.Members.OrderBy(m => m.FamilyName).ThenBy(m => m.GivenName).ToListAsync(), i => (i as Member)?.MgNr);
ControlUtils.RenewItemsSource(MemberInput, await Context.Members.Where(m => m.IsActive || !IsCreating).OrderBy(m => m.FamilyName).ThenBy(m => m.GivenName).ToListAsync(), i => (i as Member)?.MgNr);
ControlUtils.RenewItemsSource(BranchInput, await Context.Branches.OrderBy(b => b.Name).ToListAsync(), i => (i as Branch)?.ZwstId);
ControlUtils.RenewItemsSource(WineVarietyInput, await Context.WineVarieties.OrderBy(v => v.Name).ToListAsync(), i => (i as WineVar)?.SortId);
ControlUtils.RenewItemsSource(AttributesInput, await Context.WineAttributes.Where(a => IsCreating || a.IsActive).OrderBy(a => a.Name).ToListAsync(), i => (i as WineAttr)?.AttrId);
@@ -403,6 +448,7 @@ namespace Elwig.Windows {
if (IsCreating) await UpdateLsNr();
await RefreshDeliveryParts();
RefreshInputs();
}
private void FocusSearchInput(object sender, RoutedEventArgs evt) {
@@ -611,12 +657,18 @@ namespace Elwig.Windows {
ScaleId = null;
WeighingId = null;
}
ManualWeighingReason = null;
ManualWeighingInput.IsChecked = false;
LastScaleError = null;
} catch (Exception e) {
LastScaleError = e.Message.Split(": ")[^1];
WeightInput.Text = "";
ScaleId = null;
WeighingId = null;
MessageBox.Show($"Beim Wiegen ist ein Fehler aufgetreten:\n\n{e.Message}", "Waagenfehler",
MessageBoxButton.OK, MessageBoxImage.Error);
}
ManualWeighingReason = null;
ManualWeighingInput.IsChecked = false;
base.TextBox_TextChanged(WeightInput, null);
EnableWeighingButtons();
UpdateButtons();
}
@@ -692,7 +744,7 @@ namespace Elwig.Windows {
MemberInput.SelectedItem = valid ? Context.Members.Find(int.Parse(MgNrInput.Text)) : null;
}
private void MemberInput_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
private void MemberInput_SelectionChanged(object? sender, SelectionChangedEventArgs? evt) {
var m = MemberInput.SelectedItem as Member;
if (m != null) MgNrInput.Text = m.MgNr.ToString();
MemberAddressField.Text = m?.FullAddress;
@@ -716,6 +768,7 @@ namespace Elwig.Windows {
NewDeliveryPartButton.Cursor = null;
DeliveryList.SelectedItem = p?.Delivery;
DeliveryPartList.SelectedItem = null;
RefreshInputs();
InitialInputs();
}
@@ -731,17 +784,28 @@ namespace Elwig.Windows {
Mouse.OverrideCursor = Cursors.Wait;
using var doc = new DeliveryNote(p.Delivery, Context);
await doc.Generate();
Mouse.OverrideCursor = Cursors.Wait;
doc.Show();
//await doc.Print(2);
Mouse.OverrideCursor = null;
if (App.Config.Debug) {
doc.Show();
} else {
await doc.Print(2);
}
}
FinishButton.Cursor = null;
DeliveryList.SelectedItem = null;
RefreshInputs();
InitInputs();
}
private void CancelCreatingButton_Click(object sender, RoutedEventArgs evt) {
ControlUtils.RenewItemsSource(AttributesInput, Context.WineAttributes.OrderBy(a => a.Name).ToList(), i => (i as WineAttr)?.AttrId);
private async void CancelCreatingButton_Click(object sender, RoutedEventArgs evt) {
if (IsCreating && HasChanged) {
var r = MessageBox.Show("Soll der Vorgang wirklich abgebrochen werden?", "Abbrechen bestätigen",
MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
if (r != MessageBoxResult.Yes) return;
}
ControlUtils.RenewItemsSource(AttributesInput, await Context.WineAttributes.OrderBy(a => a.Name).ToListAsync(), i => (i as WineAttr)?.AttrId);
ControlUtils.RenewItemsSource(MemberInput, await Context.Members.Where(m => m.IsActive || !IsReceipt).OrderBy(m => m.FamilyName).ThenBy(m => m.GivenName).ToListAsync(), i => (i as Member)?.MgNr);
if (DeliveryList.SelectedItem is not Delivery d) {
// switch away from creating mode
IsCreating = false;
@@ -762,8 +826,11 @@ namespace Elwig.Windows {
}
}
private void NewDeliveryButton_Click(object? sender, RoutedEventArgs? evt) {
ControlUtils.RenewItemsSource(AttributesInput, Context.WineAttributes.Where(a => a.IsActive).OrderBy(a => a.Name).ToList(), i => (i as WineAttr)?.AttrId);
private async void NewDeliveryButton_Click(object? sender, RoutedEventArgs? evt) {
TodayOnlyInput.IsChecked = true;
SearchInput.Text = "";
ControlUtils.RenewItemsSource(AttributesInput, await Context.WineAttributes.Where(a => a.IsActive).OrderBy(a => a.Name).ToListAsync(), i => (i as WineAttr)?.AttrId);
ControlUtils.RenewItemsSource(MemberInput, await Context.Members.Where(m => m.IsActive || !IsReceipt).OrderBy(m => m.FamilyName).ThenBy(m => m.GivenName).ToListAsync(), i => (i as Member)?.MgNr);
IsCreating = true;
DeliveryList.IsEnabled = false;
DeliveryPartList.IsEnabled = false;
@@ -830,7 +897,7 @@ namespace Elwig.Windows {
}
private void WeighingManualButton_Click(object sender, RoutedEventArgs evt) {
var res = Utils.ShowManualWeighingDialog();
var res = Utils.ShowManualWeighingDialog(LastScaleError);
if (res == null) return;
WeightInput.Text = $"{res?.Item1:N0}";
ManualWeighingInput.IsChecked = true;
@@ -1052,8 +1119,8 @@ namespace Elwig.Windows {
}
private void ShowFinishNewPartDeliveryCancelButtons() {
FinishButton.IsEnabled = IsCreating && IsValid;
NewDeliveryPartButton.IsEnabled = IsCreating && IsValid;
FinishButton.IsEnabled = false;
NewDeliveryPartButton.IsEnabled = false;
CancelCreatingButton.IsEnabled = true;
FinishButton.Visibility = Visibility.Visible;
NewDeliveryPartButton.Visibility = Visibility.Visible;
@@ -1108,10 +1175,11 @@ namespace Elwig.Windows {
private void EnableWeighingButtons() {
WeighingManualButton.IsEnabled = true;
WeighingAButton.IsEnabled = true;
WeighingBButton.IsEnabled = true;
WeighingCButton.IsEnabled = true;
WeighingDButton.IsEnabled = true;
var n = App.Scales.Count;
WeighingAButton.IsEnabled = n > 0 && App.Scales[0].IsReady;
WeighingBButton.IsEnabled = n > 1 && App.Scales[1].IsReady;
WeighingCButton.IsEnabled = n > 2 && App.Scales[2].IsReady;
WeighingDButton.IsEnabled = n > 3 && App.Scales[3].IsReady;
}
private async Task UpdateLsNr() {
@@ -1222,8 +1290,10 @@ namespace Elwig.Windows {
}
private void ModifiersInput_SelectionChanged(object sender, ItemSelectionChangedEventArgs evt) {
if ((IsEditing || IsCreating) && App.Client.IsMatzen) {
var mod = ModifiersInput.SelectedItems.Cast<Modifier>();
if (!IsEditing && !IsCreating) return;
var mod = ModifiersInput.SelectedItems.Cast<Modifier>();
var source = ModifiersInput.ItemsSource.Cast<Modifier>();
if (App.Client.IsMatzen) {
var kl = mod.Where(m => m.Name.StartsWith("Klasse "));
if (kl.Count() > 1) {
foreach (var r in kl.Take(kl.Count() - 1)) ModifiersInput.SelectedItems.Remove(r);
@@ -1232,11 +1302,14 @@ namespace Elwig.Windows {
}
private void LesewagenInput_Changed(object sender, RoutedEventArgs evt) {
if ((IsEditing || IsCreating) && App.Client.IsMatzen) {
var mod = ModifiersInput.SelectedItems.Cast<Modifier>();
if (!IsEditing && !IsCreating) return;
var mod = ModifiersInput.SelectedItems.Cast<Modifier>();
var source = ModifiersInput.ItemsSource.Cast<Modifier>();
var lw = LesewagenInput.IsChecked == true;
if (App.Client.IsMatzen) {
var kl = mod.Where(m => m.Name.StartsWith("Klasse ")).Select(m => m.ModId).LastOrDefault("A")[0];
if (LesewagenInput.IsChecked == true) kl++; else kl--;
var newKl = ModifiersInput.ItemsSource.Cast<Modifier>().Where(m => m.ModId == kl.ToString()).FirstOrDefault();
if (lw) kl++; else kl--;
var newKl = source.Where(m => m.ModId == kl.ToString()).FirstOrDefault();
if (newKl != null) ModifiersInput.SelectedItems.Add(newKl);
}
CheckBox_Changed(sender, evt);

View File

@@ -23,7 +23,7 @@
<MenuItem Header="Über"/>
</MenuItem>
</Menu>
<Grid Height="100" VerticalAlignment="Top" Margin="0,25,0,0">
<Grid Height="100" VerticalAlignment="Top" Margin="25,25,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
@@ -38,26 +38,20 @@
HorizontalAlignment="Left" Margin="0,70,0,0" VerticalAlignment="Top"/>
</Grid>
<Button x:Name="MemberAdminButton" Content="Mitgliederverwaltung" Click="MemberAdminButton_Click"
<Button x:Name="MemberAdminButton" Content="Mitglieder" Click="MemberAdminButton_Click"
Margin="50,160,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Button x:Name="MemberListButton" Content="Mitgliederliste" Click="MemberListButton_Click"
Margin="50,200,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Button x:Name="ReceiptButton" Content="Übernahme" Click="ReceiptButton_Click"
Margin="50,200,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Button x:Name="DeliveryAdminButton" Content="Lieferungen" Click="DeliveryAdminButton_Click"
Margin="50,240,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Button x:Name="DeliveryAdminButton" Content="Lieferungsverwaltung" Click="DeliveryAdminButton_Click"
<Button x:Name="PaymentWindowButton" Content="Auszahlung" Click="PaymentWindowButton_Click"
Margin="50,280,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Button x:Name="DeliveryListButton" Content="Lieferungungen" Click="DeliveryListButton_Click" IsEnabled="False"
<Button x:Name="BaseDataButton" Content="Stammdaten" Click="BaseDataButton_Click"
Margin="50,320,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Button x:Name="BaseDataButton" Content="Stammdaten" Click="BaseDataButton_Click"
Margin="260,160,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Button x:Name="PdfButton" Content="PDF Erzeugen" Click="PdfButton_Click" Tag="Print"
Margin="260,200,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Button x:Name="TestWindowButton" Content="Test Fenster" Click="TestWindowButton_Click"
Margin="260,240,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Button x:Name="QueryWindowButton" Content="Datenbankabfragen" Click="QueryWindowButton_Click"
Margin="260,280,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Button x:Name="PaymentWindowButton" Content="Auszahlung" Click="PaymentWindowButton_Click"
<Button x:Name="QueryWindowButton" Content="Datenbankabfragen" Click="QueryWindowButton_Click"
Margin="260,320,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
</Grid>
</Window>

View File

@@ -1,20 +1,17 @@
using System.Linq;
using System.Windows;
using System.Windows.Input;
using Elwig.Documents;
using Elwig.Helpers;
using Microsoft.EntityFrameworkCore;
namespace Elwig.Windows {
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
if (!App.Config.Debug) {
TestWindowButton.Visibility = Visibility.Hidden;
//QueryWindowButton.Visibility = Visibility.Hidden;
}
}
private void Window_Loaded(object sender, RoutedEventArgs evt) {
PdfButton.IsEnabled = App.IsPrintingReady;
}
private void Window_Loaded(object sender, RoutedEventArgs evt) { }
private void MemberAdminButton_Click(object sender, RoutedEventArgs evt) {
var w = new MemberAdminWindow();
@@ -40,15 +37,6 @@ namespace Elwig.Windows {
// TODO
}
private async void PdfButton_Click(object sender, RoutedEventArgs evt) {
Mouse.OverrideCursor = Cursors.Wait;
using var ctx = new AppDbContext();
using var doc = new DeliveryNote(await ctx.Deliveries.OrderBy(d => d.Parts.Count).ThenBy(d => d.Year).ThenBy(d => d.DId).LastAsync(), ctx);
await doc.Generate();
doc.Show();
Mouse.OverrideCursor = null;
}
private void TestWindowButton_Click(object sender, RoutedEventArgs evt) {
var w = new TestWindow();
w.Show();

View File

@@ -4,7 +4,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Elwig.Windows"
Title="Mitgliederverwaltung - Elwig" Height="670" Width="1250" MinHeight="600" MinWidth="1000"
Title="Mitglieder - Elwig" Height="670" Width="1250" MinHeight="600" MinWidth="1000"
Loaded="Window_Loaded">
<Window.Resources>
<Style TargetType="Label">

View File

@@ -89,7 +89,8 @@ namespace Elwig.Windows {
.ToList();
}
ControlUtils.RenewItemsSource(MemberList, members, i => (i as Member)?.MgNr, MemberList_SelectionChanged, ControlUtils.RenewSourceDefault.IfOnly, !updateSort);
ControlUtils.RenewItemsSource(MemberList, members, i => (i as Member)?.MgNr,
MemberList_SelectionChanged, TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
}
private void RefreshInputs(bool validate = false) {

View File

@@ -5,7 +5,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Elwig.Windows"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Title="Test Fenster - Elwig" MinHeight="400" MinWidth="325" Height="450" Width="800" ResizeMode="CanResize">
Title="Test Fenster - Elwig" MinHeight="400" MinWidth="325" Height="450" Width="800" ResizeMode="CanResize" Loaded="Window_Loaded">
<Grid>
<xctk:CheckComboBox x:Name="MyComboBox" HorizontalAlignment="Left" Margin="216,186,0,0" VerticalAlignment="Top" Delimiter=", "
SelectedValue="{Binding SelectedValue}"
@@ -18,5 +18,10 @@
<TextBlock x:Name="Output" Height="20" Width="200" Margin="470,329,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Button x:Name="ChartButton" Content="Chart" Click="ChartButton_Click"
Margin="50,240,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Button x:Name="PdfDeliveryButton" Content="Lieferschein Erzeugen" Click="PdfDeliveryButton_Click" Tag="Print"
Margin="260,190,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Button x:Name="PdfCreditButton" Content="Gutschrift Erzeugen" Click="PdfCreditButton_Click" Tag="Print"
Margin="260,160,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
</Grid>
</Window>

View File

@@ -1,16 +1,26 @@
using Elwig.Documents;
using Elwig.Helpers;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using Xceed.Wpf.Toolkit.Primitives;
namespace Elwig.Windows {
public partial class TestWindow : Window {
public TestWindow() {
InitializeComponent();
MyComboBox.ItemsSource = new string[] { "Klasse A" , "Klasse B", "Klasse C", "Klasse D", "Klasse E", "Klasse F" };
MyListBox.ItemsSource = new string[] { "Test 1", "Test 2", "Test 3", "Test 4" };
}
private void Window_Loaded(object sender, RoutedEventArgs evt) {
PdfDeliveryButton.IsEnabled = App.IsPrintingReady;
PdfCreditButton.IsEnabled = App.IsPrintingReady;
}
private void OnItemSelectionChanged(object sender, ItemSelectionChangedEventArgs e) {
MyText.Text = string.Join(", ", MyComboBox.SelectedItems.Cast<string>());
}
@@ -39,5 +49,23 @@ namespace Elwig.Windows {
var w = new ChartWindow();
w.Show();
}
private async void PdfDeliveryButton_Click(object sender, RoutedEventArgs evt) {
Mouse.OverrideCursor = Cursors.Wait;
using var ctx = new AppDbContext();
using var doc = new DeliveryNote(await ctx.Deliveries.OrderBy(d => d.Parts.Count).ThenBy(d => d.Year).ThenBy(d => d.DId).LastAsync(), ctx);
await doc.Generate();
doc.Show();
Mouse.OverrideCursor = null;
}
private async void PdfCreditButton_Click(object sender, RoutedEventArgs evt) {
Mouse.OverrideCursor = Cursors.Wait;
using var ctx = new AppDbContext();
using var doc = new CreditNote(await ctx.Credits.FirstAsync(), ctx);
await doc.Generate();
doc.Show();
Mouse.OverrideCursor = null;
}
}
}

View File

@@ -1,12 +0,0 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Fragment>
<ComponentGroup Id="DocumentTemplateComponents" Directory="ConfigFolderResources">
<Component>
<File Source="$(TargetDir)\paged.polyfill.js" />
</Component>
<Component>
<File Source="$(var.ElwigProjectDir)\Documents\style.css" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>

View File

@@ -23,10 +23,10 @@
-->
<xsl:key
name="FileToRemove"
match="wix:Component[ substring( wix:File/@Source, string-length( wix:File/@Source ) - 6 ) != '.cshtml' ]"
match="wix:Component[ substring( wix:File/@Source, string-length( wix:File/@Source ) - 2 ) = '.cs' ]"
use="@Id"
/>
<!-- Get the last 4 characters of a string using `substring( s, len(s) - 3 )`, it uses -3 and not -4 because XSLT uses 1-based indexes, not 0-based indexes. -->
<!-- Get the last 3 characters of a string using `substring( s, len(s) - 2 )`, it uses -2 and not -3 because XSLT uses 1-based indexes, not 0-based indexes. -->
<!-- By default, copy all elements and nodes into the output... -->
<xsl:template match="@*|node()">

View File

@@ -2,6 +2,7 @@
[general]
; Only needed, if more than one branch is stored in database
branch = Zweigstelle
;debug = true
[database]
; Relative or absolute path to database file

View File

@@ -25,14 +25,13 @@
</Task>
</UsingTask>
<Target Name="CustomBeforeBuild" BeforeTargets="BeforeBuild">
<Exec Command="curl -s -L &quot;https://unpkg.com/pagedjs/dist/paged.polyfill.js&quot; -o &quot;$(TargetDir)paged.polyfill.js&quot;" />
<Exec Command="curl -s &quot;http://www.columbia.edu/~em36/PDFtoPrinter.exe&quot; -z &quot;$(TargetDir)PDFtoPrinter.exe&quot; -o &quot;$(TargetDir)PDFtoPrinter.exe&quot;" />
<Exec Command="dotnet publish &quot;$(SolutionDir)Elwig\Elwig.csproj&quot; &quot;/p:PublishProfile=$(SolutionDir)\Elwig\Properties\PublishProfiles\FolderProfile.pubxml&quot;" />
<GetFileVersion AssemblyPath="..\Elwig\bin\Publish\Elwig.exe">
<Output TaskParameter="Version" PropertyName="ElwigFileVersion" />
</GetFileVersion>
<PropertyGroup>
<DefineConstants>ProductVersion=$(ElwigFileVersion);BuildPath=..\Elwig\bin\Publish;DocumentTemplatesPath=..\Elwig\Documents;ElwigProjectDir=..\Elwig</DefineConstants>
<DefineConstants>ProductVersion=$(ElwigFileVersion);BuildPath=..\Elwig\bin\Publish;DocumentPath=..\Elwig\Documents;ElwigProjectDir=..\Elwig</DefineConstants>
</PropertyGroup>
</Target>
<ItemGroup>
@@ -50,13 +49,13 @@
<ComponentGroupName>DocumentTemplates</ComponentGroupName>
<DirectoryRefId>ConfigFolderResources</DirectoryRefId>
<SuppressRootDirectory>true</SuppressRootDirectory>
<PreprocessorVariable>DocumentTemplatesPath</PreprocessorVariable>
<Transforms>DocumentTemplatesTransform.xslt</Transforms>
<PreprocessorVariable>DocumentPath</PreprocessorVariable>
<Transforms>DocumentTransform.xslt</Transforms>
</HarvestDirectory>
<BindPath BindName="DocumentTemplateBindPath" Include="../Elwig/Documents" />
</ItemGroup>
<ItemGroup>
<None Include="DocumentTemplatesTransform.xslt" />
<None Include="DocumentTransform.xslt" />
<None Include="BuildFilesTransform.xslt" />
<None Include="Files\config.ini" />
</ItemGroup>

View File

@@ -11,7 +11,6 @@
<ComponentGroupRef Id="MainComponents"/>
<ComponentGroupRef Id="BuildFiles"/>
<ComponentGroupRef Id="DocumentTemplates"/>
<ComponentGroupRef Id="DocumentTemplateComponents"/>
</Feature>
</Package>
</Wix>

View File

@@ -72,14 +72,14 @@ namespace Tests {
[Test]
public void Test_SplitAddress() {
Assert.Multiple(() => {
Assert.That(Utils.SplitAddress("Winzerstra<EFBFBD>e 1"), Is.EqualTo(("Winzerstra<EFBFBD>e", "1")));
Assert.That(Utils.SplitAddress("Winzerstraße 1"), Is.EqualTo(("Winzerstraße", "1")));
Assert.That(Utils.SplitAddress("Auf dem Feld 12"), Is.EqualTo(("Auf dem Feld", "12")));
Assert.That(Utils.SplitAddress("Winzerstra<EFBFBD>e 5a"), Is.EqualTo(("Winzerstra<EFBFBD>e", "5a")));
Assert.That(Utils.SplitAddress("Winzerstra<EFBFBD>e 1-3/2"), Is.EqualTo(("Winzerstra<EFBFBD>e", "1-3/2")));
Assert.That(Utils.SplitAddress("Winzerstra<EFBFBD>e 3/4/5"), Is.EqualTo(("Winzerstra<EFBFBD>e", "3/4/5")));
Assert.That(Utils.SplitAddress("Winzerstra<EFBFBD>e 7/2/4/77"), Is.EqualTo(("Winzerstra<EFBFBD>e", "7/2/4/77")));
Assert.That(Utils.SplitAddress("Winzerstra<EFBFBD>e 95b"), Is.EqualTo(("Winzerstra<EFBFBD>e", "95b")));
Assert.That(Utils.SplitAddress("Winzerstra<EFBFBD>e 1, TOP 3"), Is.EqualTo(("Winzerstra<EFBFBD>e", "1, TOP 3")));
Assert.That(Utils.SplitAddress("Winzerstraße 5a"), Is.EqualTo(("Winzerstraße", "5a")));
Assert.That(Utils.SplitAddress("Winzerstraße 1-3/2"), Is.EqualTo(("Winzerstraße", "1-3/2")));
Assert.That(Utils.SplitAddress("Winzerstraße 3/4/5"), Is.EqualTo(("Winzerstraße", "3/4/5")));
Assert.That(Utils.SplitAddress("Winzerstraße 7/2/4/77"), Is.EqualTo(("Winzerstraße", "7/2/4/77")));
Assert.That(Utils.SplitAddress("Winzerstraße 95b"), Is.EqualTo(("Winzerstraße", "95b")));
Assert.That(Utils.SplitAddress("Winzerstraße 1, TOP 3"), Is.EqualTo(("Winzerstraße", "1, TOP 3")));
});
}