Compare commits

...

10 Commits

Author SHA1 Message Date
f5d3a04cb1 Bump version to 0.13.2
All checks were successful
Test / Run tests (push) Successful in 1m50s
Deploy / Build and Deploy (push) Successful in 2m6s
2024-10-13 19:08:20 +02:00
0675c45617 Elwig: Use ExecuteSql/FromSql instead of ExecuteSqlRaw/FromSqlRaw where possible
All checks were successful
Test / Run tests (push) Successful in 1m42s
2024-10-13 18:24:40 +02:00
d1f67dc57d BaseDataWindow: Fix WineAttr/WineCult Id updates in payment variant data
All checks were successful
Test / Run tests (push) Successful in 2m10s
2024-10-13 18:18:31 +02:00
3cbffdbf27 Documents: Add DeliveryDepreciationList
All checks were successful
Test / Run tests (push) Successful in 1m55s
2024-10-13 11:54:18 +02:00
e247925472 Controls: Fix blurry borders when system scaling is enabled
All checks were successful
Test / Run tests (push) Successful in 2m21s
2024-10-12 14:25:24 +02:00
a1b3cff624 [#11] Tests: Add DeliveryServiceTest
All checks were successful
Test / Run tests (push) Successful in 1m56s
2024-10-07 23:43:22 +02:00
65498dd18f App: Fix BranchLocation shortening
All checks were successful
Test / Run tests (push) Successful in 1m46s
2024-10-05 19:31:59 +02:00
27dc4f648f [#11] Tests: Add MemberServiceTest 2024-10-05 19:31:51 +02:00
86f7f693a0 Export/Bki: Format house nr that excel interprets it correctly
All checks were successful
Test / Run tests (push) Successful in 2m10s
2024-10-02 11:08:14 +02:00
8680e51052 Weighing: Fix scale L320 for Baden 2024-10-02 10:45:04 +02:00
46 changed files with 1913 additions and 128 deletions

View File

@ -3,6 +3,32 @@ Changelog
=========
[v0.13.2][v0.13.2] (2024-10-13) {#v0.13.2}
------------------------------------------
### Neue Funktionen {#0.13.2-features}
* Im Lieferungen-Fenster den Menüpunkt _Abwerteliste_ (`DeliveryDepreciationList`) hinzugefügt. (3cbffdbf27)
### Behobene Fehler {#0.13.2-bugfixes}
* Fehler im Waagenprotokoll `Avery-Async` (L320) behoben. (8680e51052)
* Hausnummern in der BKI Traubentransportscheinliste werden in Excel richtig angezeigt. (86f7f693a0)
* Beim Ändern der Identifikatoren von Attributen/Bewirtschaftungsarten wurden diese in Auszahlungsvarianten nicht aktualisiert. (d1f67dc57d)
### Sonstiges {#0.13.2-misc}
* Weitere automatisierte Tests hinzugefügt. ([#11][i11])
* Namenszusätze bei Gemeinden (z.B. an, bei, im, am) genauer angegeben. (65498dd18f)
* Bei einigen Eingabefeldern waren die Ränder unscharf. (e247925472)
* Wo leicht möglich wird `ExecuteSql`/`FromSql` statt `ExecuteSqlRaw`/`FromSqlRaw` verwendet. (0675c45617)
[v0.13.2]: https://git.necronda.net/winzer/elwig/releases/tag/v0.13.2
[i11]: https://git.necronda.net/winzer/elwig/issues/11
[v0.13.1][v0.13.1] (2024-09-29) {#v0.13.1}
------------------------------------------

View File

@ -7,9 +7,6 @@ using Elwig.Helpers;
using Elwig.Helpers.Weighing;
using System.Collections.Generic;
using System.Windows.Threading;
using System.Globalization;
using System.Threading;
using System.Windows.Markup;
using System.Reflection;
using Elwig.Helpers.Printing;
using Elwig.Windows;
@ -62,7 +59,7 @@ namespace Elwig {
MainDispatcher = Dispatcher;
Scales = [];
CurrentApp = this;
OverrideCulture();
Utils.OverrideCulture();
var args = Environment.GetCommandLineArgs();
if (args.Length >= 2) {
@ -82,23 +79,6 @@ namespace Elwig {
MainDispatcher.BeginInvoke(HintContextChange);
}
private static void OverrideCulture() {
var locale = new CultureInfo("de-AT", false);
locale.NumberFormat.CurrencyGroupSeparator = Utils.GroupSeparator;
locale.NumberFormat.NumberGroupSeparator = Utils.GroupSeparator;
locale.NumberFormat.PercentGroupSeparator = Utils.GroupSeparator;
CultureInfo.CurrentCulture = locale;
CultureInfo.CurrentUICulture = locale;
Thread.CurrentThread.CurrentCulture = locale;
Thread.CurrentThread.CurrentUICulture = locale;
CultureInfo.DefaultThreadCurrentCulture = locale;
CultureInfo.DefaultThreadCurrentUICulture = locale;
FrameworkElement.LanguageProperty.OverrideMetadata(
typeof(FrameworkElement),
new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.Name))
);
}
protected override async void OnStartup(StartupEventArgs evt) {
Version = new Version(typeof(App).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion.Split('+')[0] ?? "0.0.0");
@ -183,6 +163,9 @@ namespace Elwig {
}
private async void Application_Exit(object sender, ExitEventArgs evt) {
foreach (var s in EventScales) {
s.Dispose();
}
await Pdf.Cleanup();
}
@ -194,7 +177,13 @@ namespace Elwig {
ZwstId = entry.Item1;
BranchName = entry.Item2;
BranchPlz = entry.Item3;
BranchLocation = entry.Item4?.Split(" im ")[0].Split(" an ")[0].Split(" bei ")[0]; // FIXME
BranchLocation = entry.Item4?
.Split(" in ")[0]
.Split(" im ")[0]
.Split(" an ")[0]
.Split(" am ")[0]
.Split(" bei ")[0]
.Split(" beim ")[0];
BranchAddress = entry.Item5;
BranchPhoneNr = entry.Item6;
BranchFaxNr = entry.Item7;
@ -202,6 +191,7 @@ namespace Elwig {
}
public static void HintContextChange() {
if (CurrentApp == null) return;
var ch = CurrentLastWrite;
if (ch > CurrentApp.LastChanged)
CurrentApp.LastChanged = ch;

View File

@ -15,9 +15,8 @@
<ColumnDefinition Width="18"/>
</Grid.ColumnDefinitions>
<Border x:Name="Border" BorderThickness="1,1,0,1"
BorderBrush="{Binding Path=BorderBrush, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
SnapsToDevicePixels="True" Grid.RowSpan="2">
<Border x:Name="Border" BorderThickness="1,1,0,1" Grid.RowSpan="2"
BorderBrush="{Binding Path=BorderBrush, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}">
<ScrollViewer x:Name="PART_ContentHost" VerticalAlignment="Center"/>
</Border>
@ -43,6 +42,8 @@
</Setter.Value>
</Setter>
<Setter Property="TextAlignment" Value="Right"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="UseLayoutRounding" Value="True"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Gray"/>

View File

@ -7,8 +7,7 @@
<ControlTemplate TargetType="ctrl:UnitTextBox">
<Border x:Name="Border"
BorderThickness="{Binding Path=BorderThickness, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
BorderBrush="{Binding Path=BorderBrush, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
SnapsToDevicePixels="True">
BorderBrush="{Binding Path=BorderBrush, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}">
<Grid Background="{Binding Path=Background, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}">
<ScrollViewer x:Name="PART_ContentHost" VerticalAlignment="Bottom">
<ScrollViewer.Margin>
@ -32,6 +31,8 @@
</Setter.Value>
</Setter>
<Setter Property="TextAlignment" Value="Right"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="UseLayoutRounding" Value="True"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Gray"/>

View File

@ -9,8 +9,8 @@
<table class="credit">
<colgroup>
<col style="width: 25mm;"/>
<col style="width: 5mm;"/>
<col style="width: 22mm;"/>
<col style="width: 6mm;"/>
<col style="width: 21mm;"/>
<col style="width: 15mm;"/>
<col style="width: 10mm;"/>
<col style="width: 10mm;"/>
@ -51,7 +51,7 @@
<tr class="@(i == 0 ? "first" : "") @(rows == i + 1 ? "last" : "")">
@if (i == 0) {
<td rowspan="@rows">@p.LsNr</td>
<td rowspan="@rows">@p.DPNr</td>
<td rowspan="@rows" class="center narrow">@p.DPNr</td>
<td class="small">@p.Variety</td>
<td class="small">
@p.Attribute@(p.Attribute != null && p.Cultivation != null ? " / " : "")@p.Cultivation

View File

@ -9,8 +9,8 @@
<table class="delivery-confirmation">
<colgroup>
<col style="width: 25mm;"/>
<col style="width: 5mm;"/>
<col style="width: 24mm;"/>
<col style="width: 6mm;"/>
<col style="width: 23mm;"/>
<col style="width: 16mm;"/>
<col style="width: 17mm;"/>
<col style="width: 10mm;"/>
@ -60,7 +60,7 @@
<tr class="@(first ? "first" : "") @(p.Variety != lastVariety && lastVariety != "" ? "new": "") @(rows > i + 1 ? "last" : "")">
@if (first) {
<td rowspan="@rows">@p.LsNr</td>
<td rowspan="@rows">@p.DPNr</td>
<td rowspan="@rows" class="center narrow">@p.DPNr</td>
<td class="small">@p.Variety</td>
<td class="small">@p.Attribute@(p.Attribute != null && p.Cultivation != null ? " / " : "")@p.Cultivation</td>
<td class="small">@p.QualityLevel</td>

View File

@ -0,0 +1,22 @@
using Elwig.Models.Dtos;
using System.Collections.Generic;
namespace Elwig.Documents {
public class DeliveryDepreciationList : Document {
public new static string Name => "Abwertungsliste";
public string Filter;
public IEnumerable<DeliveryJournalRow> Deliveries;
public DeliveryDepreciationList(string filter, IEnumerable<DeliveryJournalRow> deliveries) :
base($"{Name} {filter}") {
Filter = filter;
Deliveries = deliveries;
}
public DeliveryDepreciationList(string filter, DeliveryJournalData data) :
this(filter, data.Rows) {
}
}
}

View File

@ -0,0 +1,104 @@
@using RazorLight
@inherits TemplatePage<Elwig.Documents.DeliveryDepreciationList>
@model Elwig.Documents.DeliveryDepreciationList
@{ Layout = "Document"; }
<link rel="stylesheet" href="file:///@Raw(Model.DataPath)\resources\DeliveryDepreciationList.css" />
<main>
<h1>Abwertungsliste</h1>
<h2>@Model.Filter</h2>
<table class="journal">
<colgroup>
<col style="width: 25mm;"/>
<col style="width: 6mm;"/>
<col style="width: 20mm;"/>
<col style="width: 15mm;"/>
<col style="width: 35mm;"/>
<col style="width: 30mm;"/>
<col style="width: 10mm;"/>
<col style="width: 10mm;"/>
<col style="width: 14mm;"/>
</colgroup>
<thead>
<tr>
<th rowspan="2" style="text-align: left;">Lieferschein-Nr.</th>
<th rowspan="2" class="narrow">Pos.</th>
<th rowspan="2">Datum</th>
<th rowspan="2">Zeit</th>
<th rowspan="2" style="text-align: left;">Sorte</th>
<th rowspan="2" style="text-align: left;">Attr./Bewirt.</th>
<th colspan="2">Gradation</th>
<th>Gewicht</th>
</tr>
<tr>
<th class="unit">[°Oe]</th>
<th class="unit narrow">[°KMW]</th>
<th class="unit">[kg]</th>
</tr>
</thead>
<tbody>
@{
int? lastMember = null;
}
@foreach (var p in Model.Deliveries) {
if (lastMember != p.MgNr) {
<tr class="subheading @(lastMember != null ? "new" : "")">
@{
var memberDeliveries = Model.Deliveries.Where(d => d.MgNr == p.MgNr).ToList();
var memberKmw = Elwig.Helpers.Utils.AggregateDeliveryPartsKmw(memberDeliveries);
var memberOe = Elwig.Helpers.Utils.KmwToOe(memberKmw);
}
<th colspan="5">
@($"{p.MgNr}, {p.AdministrativeName}")
</th>
<td>Teil-Lfrg.: <span style="float: right;">@($"{memberDeliveries.Count():N0}")</span></td>
<td class="center">@($"{memberOe:N0}")</td>
<td class="center">@($"{memberKmw:N1}")</td>
<td class="number">@($"{memberDeliveries.Sum(p => p.Weight):N0}")</td>
</tr>
}
<tr>
<td>@p.LsNr</td>
<td class="center narrow">@p.Pos</td>
<td>@($"{p.Date:dd.MM.yyyy}")</td>
<td>@($"{p.Time:HH:mm}")</td>
<td>@p.Variety</td>
<td>@p.Attribute@(p.Attribute != null && p.Cultivation != null ? " / " : "")@p.Cultivation</td>
<td class="center">@($"{p.Oe:N0}")</td>
<td class="center">@($"{p.Kmw:N1}")</td>
<td class="number">@($"{p.Weight:N0}")</td>
</tr>
lastMember = p.MgNr;
}
@{
var branches = Model.Deliveries.Select(d => d.DeliveryBranch).Distinct().Order().ToArray();
if (branches.Length > 1) {
foreach (var b in branches) {
<tr class="@(branches[0] == b ? "sum" : "") bold">
@{
var branchDeliveries = Model.Deliveries.Where(d => d.DeliveryBranch == b).ToList();
var branchKmw = Elwig.Helpers.Utils.AggregateDeliveryPartsKmw(branchDeliveries);
var branchOe = Elwig.Helpers.Utils.KmwToOe(branchKmw);
}
<td colspan="2">@b:</td>
<td colspan="4">(Teil-)Lieferungen: @($"{branchDeliveries.DistinctBy(p => p.LsNr).Count():N0}") (@($"{branchDeliveries.Count():N0}"))</td>
<td class="center">@($"{branchOe:N0}")</td>
<td class="center">@($"{branchKmw:N1}")</td>
<td class="number">@($"{branchDeliveries.Sum(p => p.Weight):N0}")</td>
</tr>
}
}
}
<tr class="sum bold">
@{
var kmw = Elwig.Helpers.Utils.AggregateDeliveryPartsKmw(Model.Deliveries);
var oe = Elwig.Helpers.Utils.KmwToOe(kmw);
}
<td colspan="2">Gesamt:</td>
<td colspan="4">(Teil-)Lieferungen: @($"{Model.Deliveries.DistinctBy(p => p.LsNr).Count():N0}") (@($"{Model.Deliveries.Count():N0}"))</td>
<td class="center">@($"{oe:N0}")</td>
<td class="center">@($"{kmw:N1}")</td>
<td class="number">@($"{Model.Deliveries.Sum(p => p.Weight):N0}")</td>
</tr>
</tbody>
</table>
</main>

View File

@ -0,0 +1,13 @@
h1 {
text-align: center;
font-size: 24pt;
margin-top: 10mm;
margin-bottom: 2mm;
}
h2 {
text-align: center;
font-size: 14pt;
margin-top: 2mm;
}

View File

@ -9,7 +9,8 @@ namespace Elwig.Documents {
public string Filter;
public IEnumerable<DeliveryJournalRow> Deliveries;
public DeliveryJournal(string filter, IEnumerable<DeliveryJournalRow> deliveries) : base($"{Name} {filter}") {
public DeliveryJournal(string filter, IEnumerable<DeliveryJournalRow> deliveries) :
base($"{Name} {filter}") {
Filter = filter;
Deliveries = deliveries;
}

View File

@ -9,10 +9,10 @@
<table class="journal">
<colgroup>
<col style="width: 25mm;"/>
<col style="width: 5mm;"/>
<col style="width: 6mm;"/>
<col style="width: 15mm;"/>
<col style="width: 8mm;"/>
<col style="width: 12mm;"/>
<col style="width: 8mm;"/>
<col style="width: 11mm;"/>
<col style="width: 38mm;"/>
<col style="width: 28mm;"/>
<col style="width: 10mm;"/>
@ -41,7 +41,7 @@
@foreach (var p in Model.Deliveries) {
<tr>
<td>@p.LsNr</td>
<td>@p.Pos</td>
<td class="center narrow">@p.Pos</td>
<td class="small">@($"{p.Date:dd.MM.yyyy}")</td>
<td class="small">@($"{p.Time:HH:mm}")</td>
<td class="number">@p.MgNr</td>
@ -52,6 +52,25 @@
<td class="number">@($"{p.Weight:N0}")</td>
</tr>
}
@{
var branches = Model.Deliveries.Select(d => d.DeliveryBranch).Distinct().Order().ToArray();
if (branches.Length > 1) {
foreach (var b in branches) {
<tr class="@(branches[0] == b ? "sum" : "") bold">
@{
var branchDeliveries = Model.Deliveries.Where(d => d.DeliveryBranch == b).ToList();
var branchKmw = Elwig.Helpers.Utils.AggregateDeliveryPartsKmw(branchDeliveries);
var branchOe = Elwig.Helpers.Utils.KmwToOe(branchKmw);
}
<td colspan="2">@b:</td>
<td colspan="5">(Teil-)Lieferungen: @($"{branchDeliveries.DistinctBy(p => p.LsNr).Count():N0}") (@($"{branchDeliveries.Count():N0}"))</td>
<td class="center">@($"{branchOe:N0}")</td>
<td class="center">@($"{branchKmw:N1}")</td>
<td class="number">@($"{branchDeliveries.Sum(p => p.Weight):N0}")</td>
</tr>
}
}
}
<tr class="sum bold">
@{
var kmw = Elwig.Helpers.Utils.AggregateDeliveryPartsKmw(Model.Deliveries);

View File

@ -78,6 +78,8 @@ namespace Elwig.Documents {
name = "CreditNote";
} else if (this is DeliveryJournal) {
name = "DeliveryJournal";
} else if (this is DeliveryDepreciationList) {
name = "DeliveryDepreciationList";
} else if (this is Letterhead) {
name = "Letterhead";
} else if (this is DeliveryConfirmation) {

View File

@ -7,7 +7,7 @@
<UseWPF>true</UseWPF>
<PreserveCompilationContext>true</PreserveCompilationContext>
<ApplicationIcon>Resources\Images\Elwig.ico</ApplicationIcon>
<Version>0.13.1</Version>
<Version>0.13.2</Version>
<SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ApplicationManifest>app.manifest</ApplicationManifest>

View File

@ -22,7 +22,7 @@ namespace Elwig.Helpers.Export {
""";
var c = App.Client;
var (a1, a2) = Utils.SplitAddress(c.Address);
_clientData = $"{c.LfbisNr};{c.NameFull};;{a1};{a2};{c.Plz};{c.Ort}";
_clientData = $"{c.LfbisNr};{c.NameFull};;{a1};\t{a2};{c.Plz};{c.Ort}";
}
public async Task ExportAsync(int year) {
@ -35,7 +35,7 @@ namespace Elwig.Helpers.Export {
WHERE year = {year}
""";
var r = await cmd.ExecuteReaderAsync();
List<Row> rows = new();
List<Row> rows = [];
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)),
@ -57,7 +57,7 @@ namespace Elwig.Helpers.Export {
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 memberData = $"{lfBisNr};{n1};{n2};{a1};\t{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}";

View File

@ -23,7 +23,7 @@ namespace Elwig.Helpers {
}
public static string? ReadUntil(this StreamReader reader, char delimiter) {
return ReadUntil(reader, new char[] { delimiter });
return ReadUntil(reader, [ delimiter ]);
}
public static string? ReadUntil(this StreamReader reader, char[] delimiter) {
@ -45,7 +45,7 @@ namespace Elwig.Helpers {
}
public static Task<string?> ReadUntilAsync(this StreamReader reader, char delimiter) {
return ReadUntilAsync(reader, new char[] { delimiter });
return ReadUntilAsync(reader, [ delimiter ]);
}
public static async Task<string?> ReadUntilAsync(this StreamReader reader, char[] delimiter) {

View File

@ -28,6 +28,9 @@ using LinqKit;
using System.Linq.Expressions;
using Elwig.Models;
using Microsoft.Win32;
using System.Globalization;
using System.Threading;
using System.Windows.Markup;
namespace Elwig.Helpers {
public static partial class Utils {
@ -118,6 +121,23 @@ namespace Elwig.Helpers {
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,
];
public static void OverrideCulture() {
var locale = new CultureInfo("de-AT", false);
locale.NumberFormat.CurrencyGroupSeparator = Utils.GroupSeparator;
locale.NumberFormat.NumberGroupSeparator = Utils.GroupSeparator;
locale.NumberFormat.PercentGroupSeparator = Utils.GroupSeparator;
CultureInfo.CurrentCulture = locale;
CultureInfo.CurrentUICulture = locale;
Thread.CurrentThread.CurrentCulture = locale;
Thread.CurrentThread.CurrentUICulture = locale;
CultureInfo.DefaultThreadCurrentCulture = locale;
CultureInfo.DefaultThreadCurrentUICulture = locale;
FrameworkElement.LanguageProperty.OverrideMetadata(
typeof(FrameworkElement),
new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.Name))
);
}
public static SerialPort OpenSerialConnection(string connection) {
var m = SerialRegex.Match(connection);
if (!m.Success)

View File

@ -58,11 +58,19 @@ namespace Elwig.Helpers.Weighing {
}
protected async Task<WeighingResult?> Receive() {
var line = await Reader.ReadUntilAsync("\r\n");
var line = "";
while (line.Length < 33) {
var ch = Reader.Read();
if (ch == -1) {
return null;
} else if (line.Length > 0 || ch == ' ') {
line += char.ToString((char)ch);
}
}
if (LogPath != null) await File.AppendAllTextAsync(LogPath, line);
if (line == null || line == "") {
return null;
} else if (line.Length != 35 || line[0] != ' ' || line[9] != ' ' || line[15] != ' ' || line[20] != ' ' || line[32] != ' ') {
} else if (line.Length != 33 || line[0] != ' ' || line[9] != ' ' || line[15] != ' ' || line[20] != ' ' || line[32] != ' ') {
throw new IOException($"Invalid event from scale: '{line}'");
}

View File

@ -34,7 +34,7 @@ namespace Elwig.Models.Dtos {
}
private static async Task<IEnumerable<AreaComUnderDeliveryRowSingle>> FromDbSet(DbSet<AreaComUnderDeliveryRowSingle> table, int year) {
return await table.FromSqlRaw($"""
return await table.FromSql($"""
SELECT m.mgnr, m.name AS name_1,
COALESCE(m.prefix || ' ', '') || m.given_name ||
COALESCE(' ' || m.middle_names, '') || COALESCE(' ' || m.suffix, '') AS name_2,

View File

@ -49,7 +49,7 @@ namespace Elwig.Models.Dtos {
}
private static async Task<IEnumerable<CreditNoteRowSingle>> FromDbSet(DbSet<CreditNoteRowSingle> table, int year, int avnr) {
return await table.FromSqlRaw($"""
return await table.FromSql($"""
SELECT m.mgnr, m.name AS name_1,
COALESCE(m.prefix || ' ', '') || m.given_name ||
COALESCE(' ' || m.middle_names, '') || COALESCE(' ' || m.suffix, '') AS name_2,

View File

@ -36,7 +36,7 @@ namespace Elwig.Models.Dtos {
}
private static async Task<IEnumerable<MemberDeliveryPerVariantRowSingle>> FromDbSet(DbSet<MemberDeliveryPerVariantRowSingle> table, int year) {
return await table.FromSqlRaw($"""
return await table.FromSql($"""
SELECT m.mgnr, m.name AS name_1,
COALESCE(m.prefix || ' ', '') || m.given_name ||
COALESCE(' ' || m.middle_names, '') || COALESCE(' ' || m.suffix, '') AS name_2,

View File

@ -25,7 +25,7 @@ namespace Elwig.Models.Dtos {
}
public static async Task<OverUnderDeliveryData> ForSeason(DbSet<OverUnderDeliveryRow> table, int year) {
var rows = await table.FromSqlRaw($"""
var rows = await table.FromSql($"""
SELECT m.mgnr, m.name AS name_1,
COALESCE(m.prefix || ' ', '') || m.given_name ||
COALESCE(' ' || m.middle_names, '') || COALESCE(' ' || m.suffix, '') AS name_2,

View File

@ -49,7 +49,7 @@ namespace Elwig.Models.Dtos {
}
private static async Task<IEnumerable<PaymentVariantSummaryRow>> FromDbSet(DbSet<PaymentVariantSummaryRow> table, int year, int avnr) {
return await table.FromSqlRaw($"""
return await table.FromSql($"""
SELECT v.type AS type,
v.name AS variety,
a.name AS attribute,

View File

@ -230,7 +230,7 @@ namespace Elwig.Services {
await ctx.SaveChangesAsync();
if (oldDsNr != null && (oldYear != year || oldDsNr != dsnr || oldMgNr != newMgNr || oldSortId != newSortId)) {
await ctx.Database.ExecuteSqlRawAsync($"UPDATE delivery_announcement SET year = {year}, dsnr = {dsnr}, mgnr = {newMgNr}, sortid = '{newSortId}' WHERE (year, dsnr, mgnr, sortid) = ({a.Year}, {a.DsNr}, {a.MgNr}, '{a.SortId}')");
await ctx.Database.ExecuteSqlAsync($"UPDATE delivery_announcement SET year = {year}, dsnr = {dsnr}, mgnr = {newMgNr}, sortid = {newSortId} WHERE (year, dsnr, mgnr, sortid) = ({a.Year}, {a.DsNr}, {a.MgNr}, {a.SortId})");
}
}

View File

@ -24,7 +24,7 @@ namespace Elwig.Services {
public static class DeliveryService {
public enum ExportSubject {
FromFilters, FromToday, FromSeasonAndBranch, Selected,
FromFilters, FromToday, FromSeason, FromSeasonAndBranch, Selected,
};
public static async Task<Member?> GetMemberAsync(int mgnr) {
@ -462,7 +462,7 @@ namespace Elwig.Services {
LNr = newLnr ?? oldDelivery!.LNr,
ZwstId = vm.Branch!.ZwstId,
LsNr = newLsNr ?? vm.LsNr!,
MgNr = (int)vm.MgNr!,
MgNr = vm.MgNr!.Value,
Comment = string.IsNullOrEmpty(vm.Comment) ? null : vm.Comment,
};
@ -474,7 +474,7 @@ namespace Elwig.Services {
SortId = vm.WineVar!.SortId,
AttrId = vm.WineAttr?.AttrId,
CultId = vm.WineCult?.CultId,
Kmw = (double)vm.GradationKmw!,
Kmw = vm.GradationKmw!.Value,
QualId = vm.WineQualityLevel!.QualId,
HkId = vm.WineOrigin!.HkId,
KgNr = vm.WineKg?.KgNr,
@ -488,7 +488,7 @@ namespace Elwig.Services {
Acid = vm.Acid,
Comment = string.IsNullOrEmpty(vm.PartComment) ? null : vm.PartComment,
Weight = (int)vm.Weight!,
Weight = vm.Weight!.Value,
IsManualWeighing = vm.IsManualWeighing,
ScaleId = vm.ScaleId,
WeighingData = vm.WeighingData,
@ -809,6 +809,71 @@ namespace Elwig.Services {
Mouse.OverrideCursor = null;
}
public static async Task GenerateDeliveryDepreciationList(this DeliveryAdminViewModel vm, ExportSubject subject, ExportMode mode) {
using var ctx = new AppDbContext();
IQueryable<DeliveryPart> query;
List<string> filterNames = [];
if (subject == ExportSubject.FromFilters) {
var (f, _, q, _, _) = await vm.GetFilters(ctx);
query = q;
filterNames.AddRange(f);
} else if (subject == ExportSubject.FromSeason) {
var year = vm.FilterSeason ?? Utils.CurrentLastSeason;
query = ctx.DeliveryParts
.Where(p => p.Year == year);
filterNames.Add($"{year}");
} else {
throw new ArgumentException("Invalid value for ExportSubject");
}
query = query
.Where(p => p.QualId == "WEI")
.OrderBy(p => p.Delivery.MgNr)
.ThenBy(p => p.Delivery.DateString)
.ThenBy(p => p.Delivery.TimeString)
.ThenBy(p => p.Delivery.LsNr)
.ThenBy(p => p.DPNr);
filterNames.Remove("abgewertet");
if (mode == ExportMode.SaveList) {
var d = new SaveFileDialog() {
FileName = $"{DeliveryDepreciationList.Name}-{vm.FilterSeason ?? Utils.CurrentLastSeason}.ods",
DefaultExt = "ods",
Filter = "OpenDocument Format Spreadsheet (*.ods)|*.ods",
Title = $"{DeliveryDepreciationList.Name} speichern unter - Elwig"
};
if (d.ShowDialog() == true) {
Mouse.OverrideCursor = Cursors.AppStarting;
try {
using var ods = new OdsFile(d.FileName);
var tblTotal = await DeliveryJournalData.FromQuery(query, filterNames);
tblTotal.FullName = DeliveryDepreciationList.Name;
tblTotal.Name = "Gesamt";
await ods.AddTable(tblTotal);
foreach (var branch in await ctx.Branches.OrderBy(b => b.Name).ToListAsync()) {
var tbl = await DeliveryJournalData.FromQuery(query.Where(p => p.Delivery.ZwstId == branch.ZwstId), filterNames);
tbl.FullName = DeliveryDepreciationList.Name;
tbl.Name = branch.Name;
await ods.AddTable(tbl);
}
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
Mouse.OverrideCursor = null;
}
} else {
Mouse.OverrideCursor = Cursors.AppStarting;
try {
var data = await DeliveryJournalData.FromQuery(query, filterNames);
using var doc = new DeliveryDepreciationList(string.Join(" / ", filterNames), data);
await Utils.ExportDocument(doc, mode);
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
Mouse.OverrideCursor = null;
}
}
private static void AddToolTipCell(Grid grid, string text, int row, int col, int colSpan = 1, bool bold = false, bool alignRight = false, bool alignCenter = false) {
var tb = new TextBlock() {
Text = text,
@ -971,5 +1036,13 @@ namespace Elwig.Services {
return (wGrid, gGrid);
}
public static async Task DeleteDelivery(string lsnr) {
using (var ctx = new AppDbContext()) {
await ctx.Deliveries.Where(d => d.LsNr == lsnr).ExecuteDeleteAsync();
await ctx.SaveChangesAsync();
}
App.HintContextChange();
}
}
}

View File

@ -25,7 +25,7 @@ namespace Elwig.Services {
public static async Task InitInputs(this MemberAdminViewModel vm) {
using var ctx = new AppDbContext();
vm.MgNrString = $"{await ctx.NextMgNr()}";
vm.MgNr = await ctx.NextMgNr();
vm.EntryDate = DateTime.Now.ToString("dd.MM.yyyy");
if (vm.BranchSource.Count() == 1)
vm.Branch = vm.BranchSource.First();
@ -53,8 +53,8 @@ namespace Elwig.Services {
public static void FillInputs(this MemberAdminViewModel vm, Member m) {
vm.IsMemberSelected = true;
vm.MgNrString = $"{m.MgNr}";
vm.PredecessorMgNrString = $"{m.PredecessorMgNr}";
vm.MgNr = m.MgNr;
vm.PredecessorMgNr = m.PredecessorMgNr;
vm.IsJuridicalPerson = m.IsJuridicalPerson;
vm.EnableMemberReferenceButton = m.PredecessorMgNr != null;
vm.Prefix = m.Prefix;
@ -73,10 +73,10 @@ namespace Elwig.Services {
vm.IsDeceased = m.IsDeceased;
vm.Address = m.Address;
if (m.PostalDest.AtPlz is AT_PlzDest p) {
vm.PlzString = $"{p.Plz}";
vm.Plz = p.Plz;
vm.Ort = ControlUtils.GetItemFromSource(vm.OrtSource, p);
} else {
vm.PlzString = null;
vm.Plz = null;
vm.Ort = null;
}
@ -114,19 +114,19 @@ namespace Elwig.Services {
vm.BillingName = billingAddr.FullName;
vm.BillingAddress = billingAddr.Address;
if (billingAddr.PostalDest.AtPlz is AT_PlzDest b) {
vm.BillingPlzString = $"{b.Plz}";
vm.BillingPlz = b.Plz;
vm.BillingOrt = ControlUtils.GetItemFromSource(vm.BillingOrtSource, b);
}
} else {
vm.BillingName = null;
vm.BillingAddress = null;
vm.BillingPlzString = null;
vm.BillingPlz = null;
vm.BillingOrt = null;
}
vm.EntryDate = (m.EntryDateString != null) ? string.Join(".", m.EntryDateString.Split("-").Reverse()) : null;
vm.ExitDate = (m.ExitDateString != null) ? string.Join(".", m.ExitDateString.Split("-").Reverse()) : null;
vm.BusinessSharesString = $"{m.BusinessShares}";
vm.BusinessShares = m.BusinessShares;
vm.AccountingNr = m.AccountingNr;
vm.Branch = (Branch?)ControlUtils.GetItemFromSourceWithPk(vm.BranchSource, m.ZwstId);
vm.DefaultKg = (AT_Kg?)ControlUtils.GetItemFromSourceWithPk(vm.DefaultKgSource, m.DefaultKgNr);
@ -148,6 +148,8 @@ namespace Elwig.Services {
vm.StatusAreaCommitmentToolTip = null;
Utils.RunBackground("Mitgliederdaten laden", async () => {
if (App.MainDispatcher == null)
return;
using var ctx = new AppDbContext();
var d1 = ctx.Deliveries.Where(d => d.Year == Utils.CurrentLastSeason - 1 && d.MgNr == m.MgNr);
@ -652,5 +654,23 @@ namespace Elwig.Services {
return newMgNr;
}
public static async Task DeleteMember(int mgnr, bool deletePaymentData, bool deleteDeliveries, bool deleteAreaComs) {
using (var ctx = new AppDbContext()) {
var l = (await ctx.Members.FindAsync(mgnr))!;
if (deletePaymentData) {
ctx.RemoveRange(l.Credits);
}
if (deleteDeliveries) {
ctx.RemoveRange(l.Deliveries);
}
if (deleteAreaComs) {
ctx.RemoveRange(l.AreaCommitments);
}
ctx.Remove(l);
await ctx.SaveChangesAsync();
}
App.HintContextChange();
}
}
}

View File

@ -96,10 +96,16 @@ namespace Elwig.ViewModels {
private IEnumerable<object> _wineCultSource = [];
[ObservableProperty]
private string? _gradationOeString;
public double? GradationOe => double.TryParse(GradationOeString, out var oe) ? oe : null;
public double? GradationOe {
get => double.TryParse(GradationOeString, out var oe) ? oe : null;
set => GradationOeString = $"{value:0}";
}
[ObservableProperty]
private string? _gradationKmwString;
public double? GradationKmw => double.TryParse(GradationKmwString, out var kmw) ? kmw : null;
public double? GradationKmw {
get => double.TryParse(GradationKmwString, out var kmw) ? kmw : null;
set => GradationKmwString = $"{value:0.0}";
}
[ObservableProperty]
private WineQualLevel? _wineQualityLevel;
[ObservableProperty]
@ -152,10 +158,16 @@ namespace Elwig.ViewModels {
private string? _partComment;
[ObservableProperty]
private string? _temperatureString;
public double? Temperature => double.TryParse(TemperatureString, out var t) ? t : null;
public double? Temperature {
get => double.TryParse(TemperatureString, out var t) ? t : null;
set => TemperatureString = $"{value:0.0}";
}
[ObservableProperty]
private string? _acidString;
public double? Acid => double.TryParse(AcidString, out var a) ? a : null;
public double? Acid {
get => double.TryParse(AcidString, out var a) ? a : null;
set => AcidString = $"{value:0.0}";
}
[ObservableProperty]
private bool _isLesewagen;
[ObservableProperty]

View File

@ -39,7 +39,7 @@ namespace Elwig.ViewModels {
[ObservableProperty]
private bool _enableSearchInputs = true;
[ObservableProperty]
private IEnumerable<bool> _memberHasDeliveries = [ .. Enumerable.Range(0, 9999).Select(i => false) ];
private IEnumerable<bool> _memberHasDeliveries = [.. Enumerable.Range(0, 9999).Select(i => false)];
[ObservableProperty]
private bool _memberListOrderByMgNr;
@ -50,10 +50,16 @@ namespace Elwig.ViewModels {
[ObservableProperty]
private string? _mgNrString;
public int? MgNr => int.TryParse(MgNrString, out var mgnr) ? mgnr : null;
public int? MgNr {
get => int.TryParse(MgNrString, out var mgnr) ? mgnr : null;
set => MgNrString = $"{value}";
}
[ObservableProperty]
private string? _predecessorMgNrString;
public int? PredecessorMgNr => int.TryParse(PredecessorMgNrString, out var mgnr) ? mgnr : null;
public int? PredecessorMgNr {
get => int.TryParse(PredecessorMgNrString, out var mgnr) ? mgnr : null;
set => PredecessorMgNrString = $"{value}";
}
[ObservableProperty]
private bool _isJuridicalPerson;
[ObservableProperty]
@ -76,7 +82,10 @@ namespace Elwig.ViewModels {
private string? _address;
[ObservableProperty]
private string? _plzString;
public int? Plz => int.TryParse(PlzString, out var plz) ? plz : null;
public int? Plz {
get => int.TryParse(PlzString, out var plz) ? plz : null;
set => PlzString = $"{value}";
}
[ObservableProperty]
private AT_PlzDest? _ort;
[ObservableProperty]
@ -88,7 +97,10 @@ namespace Elwig.ViewModels {
private string? _billingAddress;
[ObservableProperty]
private string? _billingPlzString;
public int? BillingPlz => int.TryParse(BillingPlzString, out var plz) ? plz : null;
public int? BillingPlz {
get => int.TryParse(BillingPlzString, out var plz) ? plz : null;
set => BillingPlzString = $"{value}";
}
[ObservableProperty]
private AT_PlzDest? _billingOrt;
[ObservableProperty]
@ -114,7 +126,10 @@ namespace Elwig.ViewModels {
private string? _exitDate;
[ObservableProperty]
private string? _businessSharesString;
public int? BusinessShares => int.TryParse(BusinessSharesString, out var bs) ? bs : null;
public int? BusinessShares {
get => int.TryParse(BusinessSharesString, out var bs) ? bs : null;
set => BusinessSharesString = $"{value}";
}
[ObservableProperty]
private string? _accountingNr;
[ObservableProperty]
@ -147,6 +162,14 @@ namespace Elwig.ViewModels {
public string? _number = number;
[ObservableProperty]
public string? _comment = comment;
public override bool Equals(object? obj) {
return obj is PhoneNr nr && Type == nr.Type && Number == nr.Number && Comment == nr.Comment;
}
public override int GetHashCode() {
return Type ^ (Number?.GetHashCode() ?? 0) ^ (Comment?.GetHashCode() ?? 0);
}
}
public ObservableCollection<PhoneNr> PhoneNrs { get; private set; } = [new(), new(), new(), new(), new(), new(), new(), new(), new()];

View File

@ -58,6 +58,8 @@ namespace Elwig.Windows {
foreach (var (old, attrid) in _attrs.Where(a => a.Value != null)) {
await ctx.Database.ExecuteSqlAsync($"UPDATE wine_attribute SET attrid = {attrid} WHERE attrid = {old}");
await ctx.Database.ExecuteSqlAsync($"UPDATE area_commitment_type SET vtrgid = (sortid || COALESCE(attrid, '') || COALESCE(disc, '')) WHERE attrid = {attrid}");
await ctx.Database.ExecuteSqlRawAsync($"UPDATE payment_variant SET data = REPLACE(REPLACE(data, '/{old}\"', '/{attrid}\"'), '/{old}-', '/{attrid}-')");
}
await ctx.SaveChangesAsync();

View File

@ -58,6 +58,7 @@ namespace Elwig.Windows {
foreach (var (old, cultid) in _cults.Where(c => c.Value != null)) {
await ctx.Database.ExecuteSqlAsync($"UPDATE wine_cultivation SET cultid = {cultid} WHERE cultid = {old}");
await ctx.Database.ExecuteSqlRawAsync($"UPDATE payment_variant SET data = REPLACE(data, '-{old}\"', '-{cultid}\"')");
}
await ctx.SaveChangesAsync();

View File

@ -120,6 +120,25 @@
<MenuItem x:Name="Menu_WineQualityStatistics_ModeKmw1" Header="...nach °KMW aufschlüsseln (ganze)" IsCheckable="True"
Click="Menu_WineQualityStatistics_Mode_Click"/>
</MenuItem>
<MenuItem Header="Abwertungsliste" x:Name="Menu_DeliveryDepreciationList">
<MenuItem x:Name="Menu_DeliveryDepreciationList_SaveFilters" Header="...aus Filtern speichern... (Excel)"
Click="Menu_DeliveryDepreciationList_SaveFilters_Click"/>
<MenuItem x:Name="Menu_DeliveryDepreciationList_ShowFilters" Header="...aus Filtern anzeigen (PDF)"
Click="Menu_DeliveryDepreciationList_ShowFilters_Click"/>
<MenuItem x:Name="Menu_DeliveryDepreciationList_SavePdfFilters" Header="...aus Filtern speichern... (PDF)"
Click="Menu_DeliveryDepreciationList_SavePdfFilters_Click"/>
<MenuItem x:Name="Menu_DeliveryDepreciationList_PrintFilters" Header="...aus Filtern drucken"
Click="Menu_DeliveryDepreciationList_PrintFilters_Click"/>
<Separator/>
<MenuItem x:Name="Menu_DeliveryDepreciationList_SaveSeason" Header="...von Saison speichern... (Excel)"
Click="Menu_DeliveryDepreciationList_SaveSeason_Click"/>
<MenuItem x:Name="Menu_DeliveryDepreciationList_ShowSeason" Header="...von Saison anzeigen (PDF)"
Click="Menu_DeliveryDepreciationList_ShowSeason_Click"/>
<MenuItem x:Name="Menu_DeliveryDepreciationList_SavePdfSeason" Header="...von Saison speichern... (PDF)"
Click="Menu_DeliveryDepreciationList_SavePdfSeason_Click"/>
<MenuItem x:Name="Menu_DeliveryDepreciationList_PrintSeason" Header="...von Saison drucken"
Click="Menu_DeliveryDepreciationList_PrintSeason_Click"/>
</MenuItem>
<MenuItem Header="BKI">
<MenuItem x:Name="Menu_Bki_SaveList" Header="Traubentransportscheinliste speichern..."/>
</MenuItem>

View File

@ -172,9 +172,11 @@ namespace Elwig.Windows {
Title = $"Traubentransportscheinliste (BKI) speichern unter - Elwig"
};
if (d.ShowDialog() == true) {
Mouse.OverrideCursor = Cursors.AppStarting;
using var file = new Bki(d.FileName);
await file.ExportAsync(year);
Mouse.OverrideCursor = Cursors.Wait;
await Task.Run(async () => {
using var file = new Bki(d.FileName);
await file.ExportAsync(year);
});
Mouse.OverrideCursor = null;
}
}
@ -250,6 +252,23 @@ namespace Elwig.Windows {
await App.Client.UpdateValues();
}
private async void Menu_DeliveryDepreciationList_SaveFilters_Click(object sender, RoutedEventArgs evt) =>
await ViewModel.GenerateDeliveryDepreciationList(DeliveryService.ExportSubject.FromFilters, ExportMode.SaveList);
private async void Menu_DeliveryDepreciationList_ShowFilters_Click(object sender, RoutedEventArgs evt) =>
await ViewModel.GenerateDeliveryDepreciationList(DeliveryService.ExportSubject.FromFilters, ExportMode.Show);
private async void Menu_DeliveryDepreciationList_SavePdfFilters_Click(object sender, RoutedEventArgs evt) =>
await ViewModel.GenerateDeliveryDepreciationList(DeliveryService.ExportSubject.FromFilters, ExportMode.SavePdf);
private async void Menu_DeliveryDepreciationList_PrintFilters_Click(object sender, RoutedEventArgs evt) =>
await ViewModel.GenerateDeliveryDepreciationList(DeliveryService.ExportSubject.FromFilters, ExportMode.Print);
private async void Menu_DeliveryDepreciationList_SaveSeason_Click(object sender, RoutedEventArgs evt) =>
await ViewModel.GenerateDeliveryDepreciationList(DeliveryService.ExportSubject.FromSeason, ExportMode.SaveList);
private async void Menu_DeliveryDepreciationList_ShowSeason_Click(object sender, RoutedEventArgs evt) =>
await ViewModel.GenerateDeliveryDepreciationList(DeliveryService.ExportSubject.FromSeason, ExportMode.Show);
private async void Menu_DeliveryDepreciationList_SavePdfSeason_Click(object sender, RoutedEventArgs evt) =>
await ViewModel.GenerateDeliveryDepreciationList(DeliveryService.ExportSubject.FromSeason, ExportMode.SavePdf);
private async void Menu_DeliveryDepreciationList_PrintSeason_Click(object sender, RoutedEventArgs evt) =>
await ViewModel.GenerateDeliveryDepreciationList(DeliveryService.ExportSubject.FromSeason, ExportMode.Print);
private void Menu_Settings_EnableFreeEditing_Checked(object sender, RoutedEventArgs evt) {
if (IsEditing || IsCreating) {
DateInput.IsReadOnly = false;
@ -933,12 +952,13 @@ namespace Elwig.Windows {
"Lieferung löschen", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel);
if (r == MessageBoxResult.OK) {
Mouse.OverrideCursor = Cursors.AppStarting;
using (var ctx = new AppDbContext()) {
ctx.Remove(d);
await ctx.SaveChangesAsync();
try {
await DeliveryService.DeleteDelivery(d.LsNr);
} catch (Exception exc) {
var str = "Der Eintrag konnte nicht in der Datenbank aktualisiert werden!\n\n" + exc.Message;
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
MessageBox.Show(str, "Lieferung löschen", MessageBoxButton.OK, MessageBoxImage.Error);
}
await RefreshList();
await RefreshDeliveryParts();
Mouse.OverrideCursor = null;
}
}

View File

@ -360,21 +360,7 @@ namespace Elwig.Windows {
if (d.ShowDialog() == true) {
Mouse.OverrideCursor = Cursors.AppStarting;
try {
using (var ctx = new AppDbContext()) {
var l = (await ctx.Members.FindAsync(m.MgNr))!;
if (d.DeletePaymentData) {
ctx.RemoveRange(l.Credits);
}
if (d.DeleteDeliveries) {
ctx.RemoveRange(l.Deliveries);
}
if (d.DeleteAreaComs) {
ctx.RemoveRange(l.AreaCommitments);
}
ctx.Remove(l);
await ctx.SaveChangesAsync();
}
App.HintContextChange();
await MemberService.DeleteMember(m.MgNr, d.DeletePaymentData, d.DeleteDeliveries, d.DeleteAreaComs);
} catch (Exception exc) {
var str = "Der Eintrag konnte nicht in der Datenbank aktualisiert werden!\n\n" + exc.Message;
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;

View File

@ -30,6 +30,11 @@ namespace Tests {
await BillingData.Init();
}
[OneTimeSetUp]
public void Setup_4_Culture() {
Utils.OverrideCulture();
}
[OneTimeTearDown]
public async Task TeardownDatabase() {
AppDbContext.ConnectionStringOverride = null;

View File

@ -29,9 +29,10 @@ namespace Tests.DocumentTests {
Assert.That(text, Contains.Substring("AT81 1234 5678 9012 3457"));
Assert.That(text, Contains.Substring("""
20201001X001 1 Grüner Veltliner 73 15,0 ungeb.: 3 219 0,5000 - - 1 609,50
20201001X003 1 Grüner Veltliner 75 15,4 ungeb.: 2 561 - -
20201001X003 2 Grüner Veltliner Kabinett 87 17,6 ungeb.: 3 129 - -
20201001X003 3 Grüner Veltliner 79 16,1 ungeb.: 1 280 - -
20201001X003 1 Grüner Veltliner abgew. 75 15,4 ungeb.: 2 561 - -
20201001X003 2 Grüner Veltliner Kabinett / abgew.
87 17,6 ungeb.: 3 129 - -
20201001X003 3 Grüner Veltliner abgew. 79 16,1 ungeb.: 1 280 - -
20201001X005 1 Welschriesling 84 17,0 ungeb.: 3 192 - -
20201001X005 2 Welschriesling 84 17,1 ungeb.: 2 190 - -
"""));

View File

@ -24,10 +24,10 @@ namespace Tests.DocumentTests {
Assert.That(text, Contains.Substring($"Wolkersdorf, am {Elwig.Helpers.Utils.Today:dd.MM.yyyy}"));
Assert.That(text, Contains.Substring("Anlieferungsbestätigung 2020"));
Assert.That(text, Contains.Substring("""
20201001X003 2 Grüner Veltliner Kabinett Kabinett 87 17,6 ungeb.: 3 129 3 129
20201001X003 3 Grüner Veltliner Qualitätswein 79 16,1 ungeb.: 1 280 1 280
20201001X003 1 Grüner Veltliner Qualitätswein 75 15,4 ungeb.: 2 561 2 561
20201001X001 1 Grüner Veltliner Qualitätswein 73 15,0 ungeb.: 3 219 3 219
20201001X003 2 Grüner Veltliner Kabinett Wein 87 17,6 ungeb.: 3 129 3 129
20201001X003 3 Grüner Veltliner Wein 79 16,1 ungeb.: 1 280 1 280
20201001X003 1 Grüner Veltliner Wein 75 15,4 ungeb.: 2 561 2 561
20201001X005 2 Welschriesling Kabinett 84 17,1 ungeb.: 2 190 2 190
20201001X005 1 Welschriesling Kabinett 84 17,0 ungeb.: 3 192 3 192
"""));

View File

@ -0,0 +1,32 @@
using Elwig.Documents;
using Elwig.Helpers;
using Elwig.Models.Dtos;
namespace Tests.DocumentTests {
[TestFixture]
public class DeliveryDepreciationListTest {
[Test]
public async Task Test_01_DepreciatedDeliveries2020() {
using var ctx = new AppDbContext();
var data = await DeliveryJournalData.FromQuery(ctx.Deliveries.Where(d => d.Year == 2020).SelectMany(d => d.Parts).Where(d => d.QualId == "WEI"), ["Saison 2020"]);
using var doc = new DeliveryDepreciationList("Saison 2020", data);
var text = await Utils.GeneratePdfText(doc, true);
var table = Utils.ExtractTable(text);
Assert.Multiple(() => {
Assert.That(text, Contains.Substring("Abwertungsliste"));
Assert.That(text, Contains.Substring("Saison 2020"));
Assert.That(table, Is.EqualTo(new string[][] {
["101, MUSTERMANN Max", "Teil-Lfrg.:", "3", "81", "16,5", "6 970"],
["20201001X003 1 01.10.2020 10:24", "Grüner Veltliner", "75", "15,4", "2 561"],
["20201001X003 2 01.10.2020 10:24", "Grüner Veltliner", "Kabinett", "87", "17,6", "3 129"],
["20201001X003 3 01.10.2020 10:24", "Grüner Veltliner", "79", "16,1", "1 280"],
["103, MUSTERBAUER Matthäus", "Teil-Lfrg.:", "2", "79", "16,2", "6 099"],
["20201002X001 1 02.10.2020 09:13", "Grüner Veltliner", "Bio", "80", "16,3", "3 198"],
["20201002X002 1 02.10.2020 09:28", "Grüner Veltliner", "Bio", "78", "16,0", "2 901"],
["Gesamt:", "(Teil-)Lieferungen: 3 (5)", "80", "16,3", "13 069"],
}));
});
}
}
}

View File

@ -84,20 +84,20 @@ namespace Tests.DocumentTests {
Assert.That(text, Contains.Substring("Traubenübernahmeschein Nr. 20201001X003"));
Assert.That(text, Contains.Substring("Das Mitglied erklärt, dass die gelieferte Ware dem österreichischen Weingesetz entspricht"));
Assert.That(text, Contains.Substring("""
1 Grüner Veltliner Qualitätswein 75 15,4 2 561
Herkunft: Österreich / Weinland / Niederösterreich
1 Grüner Veltliner Wein 75 15,4 2 561
Herkunft: Österreich
/ Matzner Hügel / Hohenruppersdorf / KG Hohenruppersdorf
Waage: ?, ID: ? (gerebelt gewogen)
"""));
Assert.That(text, Contains.Substring("""
2 Grüner Veltliner Kabinett Kabinett 87 17,6 3 129
Herkunft: Österreich / Weinland / Niederösterreich
2 Grüner Veltliner Kabinett Wein 87 17,6 3 129
Herkunft: Österreich
/ Matzner Hügel / Hohenruppersdorf / KG Hohenruppersdorf
Waage: ?, ID: ? (gerebelt gewogen)
"""));
Assert.That(text, Contains.Substring("""
3 Grüner Veltliner Qualitätswein 79 16,1 1 280
Herkunft: Österreich / Weinland / Niederösterreich
3 Grüner Veltliner Wein 79 16,1 1 280
Herkunft: Österreich
/ Matzner Hügel / Hohenruppersdorf / KG Hohenruppersdorf
Waage: ?, ID: ? (gerebelt gewogen)
"""));
@ -123,9 +123,9 @@ namespace Tests.DocumentTests {
Assert.That(text, Contains.Substring("Traubenübernahmeschein Nr. 20201002X001"));
Assert.That(text, Contains.Substring("Das Mitglied erklärt, dass die gelieferte Ware dem österreichischen Weingesetz entspricht"));
Assert.That(text, Contains.Substring("""
1 Grüner Veltliner Qualitätswein 80 16,3 3 198
1 Grüner Veltliner Wein 80 16,3 3 198
Bewirtschaftung: Bio (AT-BIO-302)
Herkunft: Österreich / Weinland / Niederösterreich
Herkunft: Österreich
/ Wolkersdorfer Hochleithen / Wolkersdorf im Weinviertel / KG Wolkersdorf
Waage: ?, ID: ? (gerebelt gewogen)
"""));

View File

@ -16,14 +16,19 @@ namespace Tests.DocumentTests {
Assert.That(text, Contains.Substring("Qualitätsstatistik"));
Assert.That(text, Contains.Substring("Saison 2020"));
Assert.That(text, Contains.Substring("""
Qualitätswein
73 2 4 431
74 2 4 203
75 3 5 176
77 1 842
Wein
75 1 2 561
78 1 2 901
79 1 1 280
80 1 3 198
87 1 3 129
"""));
Assert.That(text, Contains.Substring("""
Qualitätswein
73 2 4 431
74 2 4 203
75 2 2 615
77 1 842
82 1 4 002
"""));
Assert.That(text, Contains.Substring("""
@ -31,14 +36,14 @@ namespace Tests.DocumentTests {
84 3 8 960
85 3 11 181
86 1 2 987
87 2 5 002
87 1 1 873
89 2 4 723
"""));
Assert.That(text, Contains.Substring(
"80 5 " + "13 069 " +
"- 0 0 " +
"- 0 0 " +
"77 12 " + "26 033 " +
"86 11 " + "32 853"));
"77 5 " + "11 568 " +
"85 6 " + "17 561"));
});
}
}

View File

@ -43,17 +43,17 @@ INSERT INTO delivery_part (year, did, dpnr, sortid, attrid, cultid, weight, kmw,
(2020, 1, 1, 'GV', NULL, NULL, 3219, 15.0, 'QUW', 'WLNO', 06109, TRUE, FALSE, FALSE, '1', '{"id":"321","nr":321,"gross_weight":3219,"tare_weight":0,"net_weight":3219,"date":"2020-10-01","time":"09:02:46"}', NULL),
(2020, 2, 1, 'GV', 'K', NULL, 2987, 17.5, 'KAB', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 2, 2, 'GV', 'K', NULL, 1873, 17.7, 'KAB', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 3, 1, 'GV', NULL, NULL, 2561, 15.4, 'QUW', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 3, 2, 'GV', 'K', NULL, 3129, 17.6, 'KAB', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 3, 3, 'GV', NULL, NULL, 1280, 16.1, 'QUW', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 3, 1, 'GV', NULL, NULL, 2561, 15.4, 'WEI', 'OEST', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 3, 2, 'GV', 'K', NULL, 3129, 17.6, 'WEI', 'OEST', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 3, 3, 'GV', NULL, NULL, 1280, 16.1, 'WEI', 'OEST', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 4, 1, 'GV', NULL, NULL, 4002, 16.7, 'QUW', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 4, 2, 'GV', NULL, NULL, 481, 15.3, 'QUW', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 5, 1, 'WR', NULL, NULL, 3192, 17.0, 'KAB', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 5, 2, 'WR', NULL, NULL, 2190, 17.1, 'KAB', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 6, 1, 'GV', NULL, 'B', 1732, 15.2, 'QUW', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 7, 1, 'GV', NULL, 'B', 3198, 16.3, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 7, 1, 'GV', NULL, 'B', 3198, 16.3, 'WEI', 'OEST', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 7, 2, 'GV', NULL, 'B', 2134, 15.4, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 8, 1, 'GV', NULL, 'B', 2901, 16.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 8, 1, 'GV', NULL, 'B', 2901, 16.0, 'WEI', 'OEST', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 8, 2, 'GV', NULL, 'B', 3321, 17.3, 'KAB', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 9, 1, 'WR', NULL, 'B', 3998, 17.2, 'KAB', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 10, 1, 'ZW', NULL, NULL, 1212, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),

View File

@ -70,7 +70,7 @@ INSERT INTO member (mgnr, given_name, name, zwstid, volllieferant, buchführend,
(101, 'Max', 'Mustermann', 'X', FALSE, FALSE, 40, 222303524, 'Winzerstraße 1', 06109, 'AT811234567890123457', '0123463', NULL ),
(102, 'Wernhardt', 'Weinbauer', 'X', FALSE, FALSE, 40, 222303524, 'Winzerstraße 2', 06109, 'AT541234567890123458', '0123471', 'ATU12345684'),
(103, 'Matthäus', 'Musterbauer', 'X', FALSE, FALSE, 40, 212005138, 'Brünner Straße 10', 15224, 'AT271234567890123459', '0123480', NULL ),
(104, 'Waltraud', 'Winzer', 'X', FALSE, FALSE, 40, 212005138, 'Wiener Straße 15', 15224, 'AT971234567890123460', '0123498', 'ATU12345693');
(104, 'Waltraud', 'Winzer', 'X', FALSE, TRUE , 40, 212005138, 'Wiener Straße 15', 15224, 'AT971234567890123460', '0123498', 'ATU12345693');
INSERT INTO member_billing_address (mgnr, name, country, postal_dest, address) VALUES
(102, 'W&B Weinbauer GesbR', 40, 222303524, 'Winzerstraße 2'),

View File

@ -0,0 +1,11 @@
-- deletes for ServiceTests
DELETE FROM credit;
DELETE FROM payment_variant;
DELETE FROM delivery;
DELETE FROM season;
DELETE FROM area_commitment;
DELETE FROM area_commitment_type;
DELETE FROM member WHERE mgnr >= 200;
DELETE FROM wine_cultivation;
DELETE FROM wine_attribute;

View File

@ -0,0 +1,135 @@
-- inserts for ServiceTests
INSERT INTO wine_cultivation (cultid, name, description) VALUES
('B', 'Bio', 'AT-BIO-302');
INSERT INTO wine_attribute (attrid, name, active, max_kg_per_ha, strict, fill_lower) VALUES
('K', 'Kabinett', TRUE, NULL, FALSE, 0);
INSERT INTO member (mgnr, given_name, name, zwstid, volllieferant, buchführend, country, postal_dest, address, default_kgnr, iban, lfbis_nr, ustid_nr) VALUES
(201, 'Theodor', 'Testbauer', 'X', FALSE, FALSE, 40, 222303524, 'Teststraße 1', 06109, 'AT811234567890123457', '0123463', NULL ),
(202, 'Thomas', 'Testmann', 'X', FALSE, FALSE, 40, 222303524, 'Teststraße 2', 06109, 'AT541234567890123458', '0123471', 'ATU12345684'),
(203, 'Tina', 'Testwinzer', 'X', FALSE, FALSE, 40, 212005138, 'Teststraße 3', 15224, 'AT271234567890123459', '0123480', NULL ),
(204, 'Trude', 'Testerin', 'X', FALSE, TRUE , 40, 212005138, 'Teststraße 4', 15224, 'AT971234567890123460', '0123498', 'ATU12345693');
INSERT INTO member_billing_address (mgnr, name, country, postal_dest, address) VALUES
(202, 'T&T Testmann GesbR', 40, 222303524, 'Teststraße 11'),
(203, 'Testwinzer GesbR', 40, 212005138, 'Teststraße 3' ),
(204, 'Trauben Trude GmbH', 40, 212205137, 'Teststraße 12');
INSERT INTO member_telephone_number (mgnr, nr, type, number, comment) VALUES
(203, 1, 'mobile', '+43 664 987654321', NULL),
(204, 1, 'mobile', '+43 664 123456789', NULL);
INSERT INTO member_email_address (mgnr, nr, address, comment) VALUES
(203, 1, 'tina@winzer.com', NULL),
(204, 1, 'trude@trauben.at', NULL);
INSERT INTO area_commitment_type (vtrgid, sortid, attrid, disc, min_kg_per_ha, penalty_per_kg, penalty_amount, penalty_none) VALUES
('GV', 'GV', NULL, NULL, 5000, 500, NULL, NULL);
INSERT INTO area_commitment (fbnr, mgnr, vtrgid, cultid, area, kgnr, gstnr, rdnr, year_from, year_to) VALUES
( 1, 203, 'GV', NULL, 10000, 15224, '321/9', NULL, NULL, NULL),
( 2, 204, 'GV', NULL, 10000, 15224, '123/1', NULL, 2000, 2019),
( 3, 204, 'GV', NULL, 10000, 15224, '123/2', NULL, 2025, 2030),
( 4, 204, 'GV', NULL, 10000, 15224, '123/3', NULL, 2021, 2031);
INSERT INTO season (year, currency, min_kg_per_bs, max_kg_per_bs, penalty_per_kg, penalty_amount, penalty_none, start_date, end_date) VALUES
(2021, 'EUR', 2000, 4000, NULL, NULL, NULL, NULL, NULL),
(2022, 'EUR', 2000, 4000, NULL, NULL, NULL, NULL, NULL),
(2023, 'EUR', 2000, 4000, NULL, NULL, NULL, NULL, NULL);
INSERT INTO modifier (year, modid, ordering, name, abs, rel, active) VALUES
(2021, 'S', 0, 'Geschädigte Trauben', NULL, -0.1, TRUE),
(2022, 'S', 0, 'Geschädigte Trauben', NULL, -0.1, TRUE);
INSERT INTO delivery (mgnr, year, did, date, time, zwstid, lnr) VALUES
(203, 2021, 1, '2021-10-01', NULL, 'X', 1),
(204, 2021, 2, '2021-10-01', NULL, 'X', 2),
(101, 2022, 1, '2022-09-29', NULL, 'X', 1),
(101, 2022, 2, '2022-09-30', NULL, 'X', 1),
(101, 2023, 1, '2023-10-01', NULL, 'X', 1),
(101, 2023, 2, '2023-10-01', NULL, 'X', 2),
(101, 2023, 3, '2023-10-01', NULL, 'X', 3),
(101, 2023, 4, '2023-10-01', NULL, 'X', 4),
(101, 2023, 5, '2023-10-02', NULL, 'X', 1),
(101, 2023, 6, '2023-10-03', NULL, 'X', 1),
(101, 2023, 7, '2023-10-04', NULL, 'X', 1),
(101, 2023, 8, '2023-10-05', NULL, 'X', 1),
(101, 2023, 9, '2023-10-06', NULL, 'X', 1),
(101, 2023, 10, '2023-10-06', NULL, 'X', 2),
(101, 2023, 11, '2023-10-07', NULL, 'X', 1),
(101, 2023, 12, '2023-10-07', NULL, 'X', 2),
(101, 2023, 13, '2023-10-08', NULL, 'X', 1),
(101, 2023, 14, '2023-10-08', NULL, 'X', 2),
(101, 2023, 15, '2023-10-09', NULL, 'X', 1),
(101, 2023, 16, '2023-10-09', NULL, 'X', 2),
(101, 2023, 17, '2023-10-10', NULL, 'X', 1),
(101, 2023, 18, '2023-10-10', NULL, 'X', 2),
(101, 2023, 19, '2023-10-10', NULL, 'X', 3);
INSERT INTO delivery_part (year, did, dpnr, sortid, attrid, cultid, weight, kmw, qualid, hkid, kgnr, net_weight, manual_weighing, spl_check, scale_id, weighing_data, weighing_reason) VALUES
(2021, 1, 1, 'GV', NULL, NULL, 3500, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2021, 2, 1, 'GV', NULL, NULL, 4000, 17.0, 'KAB', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2021, 2, 2, 'GV', NULL, NULL, 4000, 16.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2022, 1, 1, 'GV', NULL, NULL, 3700, 16.5, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2022, 1, 2, 'GV', NULL, NULL, 3700, 16.5, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 1, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 1, 2, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 1, 3, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 2, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 2, 2, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 2, 3, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 3, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 3, 2, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 3, 3, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 4, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 4, 2, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 4, 3, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 5, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 5, 2, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 5, 3, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 6, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 6, 2, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 6, 3, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 7, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 7, 2, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 7, 3, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 8, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 8, 2, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 8, 3, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 9, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 9, 2, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 9, 3, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 10, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 11, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 11, 2, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 11, 3, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 12, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 13, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 13, 2, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 13, 3, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 14, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 15, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 15, 2, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 15, 3, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 16, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 17, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 18, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2023, 19, 1, 'GV', NULL, NULL, 1000, 15.0, 'QUW', 'WLNO', 15224, TRUE, FALSE, FALSE, NULL, NULL, NULL);
INSERT INTO delivery_part_modifier (year, did, dpnr, modid) VALUES
(2021, 1, 1, 'S'),
(2021, 2, 2, 'S'),
(2022, 1, 2, 'S');
INSERT INTO payment_variant (year, avnr, name, date, transfer_date, test_variant, calc_time, comment, data) VALUES
(2021, 1, 'Probevariante', '2022-01-15', '2022-01-15', TRUE, NULL, NULL, '{"mode":"elwig","version":1,"payment":0.5,"curves":[]}');
INSERT INTO payment_member (year, avnr, mgnr, net_amount) VALUES
(2021, 1, 203, 10000000),
(2021, 1, 204, 10000000);
INSERT INTO credit (year, tgnr, mgnr, avnr, net_amount, prev_net_amount, vat, modifiers, prev_modifiers) VALUES
(2021, 1, 203, 1, 10000000, 0, 0.1, 0, 0),
(2021, 2, 204, 1, 10000000, 0, 0.1, 0, 0);

View File

@ -0,0 +1,847 @@
using Elwig.Helpers;
using Elwig.Models.Entities;
using Elwig.Services;
using Elwig.ViewModels;
using Microsoft.EntityFrameworkCore;
namespace Tests.ServiceTests {
[TestFixture]
public class DeliveryServiceTest {
private static async Task InitViewModel(DeliveryAdminViewModel vm) {
using var ctx = new AppDbContext();
vm.MemberSource = await ctx.Members.ToListAsync();
vm.BranchSource = await ctx.Branches.ToListAsync();
vm.WineVarSource = await ctx.WineVarieties.ToListAsync();
List<object> attrs = (await ctx.WineAttributes.ToListAsync()).Cast<object>().ToList();
attrs.Insert(0, new NullItem());
vm.WineAttrSource = attrs;
List<object> cults = (await ctx.WineCultivations.ToListAsync()).Cast<object>().ToList();
cults.Insert(0, new NullItem());
vm.WineCultSource = cults;
vm.WineQualityLevelSource = await ctx.WineQualityLevels.ToListAsync();
vm.WineOriginSource = await ctx.WineOrigins.ToListAsync();
vm.WineKgSource = await ctx.Katastralgemeinden.ToListAsync();
vm.ModifiersSource = await ctx.Modifiers.Where(m => m.Year == 2022).ToListAsync();
}
private static async Task<Delivery?> GetDelivery(string lsnr) {
using var ctx = new AppDbContext();
return await ctx.Deliveries
.Where(d => d.LsNr == lsnr)
.Include(d => d.Parts)
.ThenInclude(p => p.PartModifiers)
.ThenInclude(m => m.Modifier)
.AsSplitQuery()
.FirstOrDefaultAsync();
}
private static DeliveryPart[] GetParts(Delivery d) {
return [.. d.Parts.OrderBy(p => p.DPNr)];
}
[Test]
public async Task TestCreate_01_Minimal() {
var vm = new DeliveryAdminViewModel();
await InitViewModel(vm);
vm.Date = "01.10.2022";
vm.Branch = vm.BranchSource.First();
vm.MgNr = 101;
vm.Member = vm.MemberSource.First(m => m.MgNr == vm.MgNr);
vm.SortId = "GV";
vm.WineVar = vm.WineVarSource.First(v => v.SortId == vm.SortId);
vm.GradationKmw = 15.0;
vm.GradationOe = 73;
vm.Weight = 1234;
vm.IsManualWeighing = true;
vm.IsNetWeight = false;
vm.WineQualityLevel = vm.WineQualityLevelSource.First(l => l.QualId == "QUW");
vm.WineOrigin = vm.WineOriginSource.First(o => o.HkId == "WLNO");
var p1 = await vm.UpdateDeliveryPart(2022, null, null, false, false, true);
Assert.That(p1.Delivery.LsNr, Is.EqualTo("20221001X001"));
var d = await GetDelivery("20221001X001");
Assert.That(d, Is.Not.Null);
Assert.That(d.Parts, Has.Count.EqualTo(1));
var p = d.Parts.First();
Assert.That(p, Is.Not.Null);
Assert.Multiple(() => {
Assert.That(d.LsNr, Is.EqualTo("20221001X001"));
Assert.That(d.Date, Is.EqualTo(new DateOnly(2022, 10, 1)));
Assert.That(d.ZwstId, Is.EqualTo("X"));
Assert.That(d.MgNr, Is.EqualTo(101));
Assert.That(p.SortId, Is.EqualTo("GV"));
Assert.That(p.AttrId, Is.Null);
Assert.That(p.CultId, Is.Null);
Assert.That(p.Kmw, Is.EqualTo(15.0));
Assert.That(p.Oe, Is.EqualTo(73));
Assert.That(p.QualId, Is.EqualTo("QUW"));
Assert.That(p.Weight, Is.EqualTo(1234));
Assert.That(p.IsNetWeight, Is.False);
Assert.That(p.IsManualWeighing, Is.True);
Assert.That(p.HkId, Is.EqualTo("WLNO"));
});
vm = new DeliveryAdminViewModel();
await InitViewModel(vm);
Assert.DoesNotThrow(() => {
vm.FillInputs(d);
vm.FillInputs(p);
});
Assert.Multiple(() => {
Assert.That(vm.LsNr, Is.EqualTo("20221001X001"));
Assert.That(vm.Date, Is.EqualTo("01.10.2022"));
Assert.That(vm.Branch?.ZwstId, Is.EqualTo("X"));
Assert.That(vm.MgNr, Is.EqualTo(101));
Assert.That(vm.SortId, Is.EqualTo("GV"));
Assert.That(vm.WineAttr?.AttrId, Is.Null);
Assert.That(vm.WineCult?.CultId, Is.Null);
Assert.That(vm.GradationKmw, Is.EqualTo(15.0));
Assert.That(vm.WineQualityLevel?.QualId, Is.EqualTo("QUW"));
Assert.That(vm.Weight, Is.EqualTo(1234));
Assert.That(vm.IsNetWeight, Is.False);
Assert.That(vm.IsManualWeighing, Is.True);
Assert.That(vm.WineOrigin?.HkId, Is.EqualTo("WLNO"));
});
}
[Test]
public async Task TestCreate_02_Advanced() {
var vm = new DeliveryAdminViewModel();
await InitViewModel(vm);
vm.Date = "02.10.2022";
vm.Branch = vm.BranchSource.First();
vm.MgNr = 102;
vm.Member = vm.MemberSource.First(m => m.MgNr == vm.MgNr);
vm.SortId = "ZW";
vm.WineVar = vm.WineVarSource.First(v => v.SortId == vm.SortId);
vm.WineAttr = vm.WineAttrSource.Skip(1).First() as WineAttr;
vm.WineCult = vm.WineCultSource.Skip(1).First() as WineCult;
vm.GradationKmw = 15.9;
vm.GradationOe = 78;
vm.Weight = 3456;
vm.IsManualWeighing = false;
vm.IsNetWeight = true;
vm.WeighingData = "{}";
vm.WineQualityLevel = vm.WineQualityLevelSource.First(l => l.QualId == "QUW");
vm.WineOrigin = vm.WineOriginSource.First(o => o.HkId == "WLNO");
vm.Modifiers.Add(vm.ModifiersSource.First());
var p1 = await vm.UpdateDeliveryPart(2022, null, null, false, false, true);
Assert.That(p1.Delivery.LsNr, Is.EqualTo("20221002X001"));
var d = await GetDelivery("20221002X001");
Assert.That(d, Is.Not.Null);
Assert.That(d.Parts, Has.Count.EqualTo(1));
var p = d.Parts.First();
Assert.That(p, Is.Not.Null);
Assert.Multiple(() => {
Assert.That(d.LsNr, Is.EqualTo("20221002X001"));
Assert.That(d.Date, Is.EqualTo(new DateOnly(2022, 10, 2)));
Assert.That(d.ZwstId, Is.EqualTo("X"));
Assert.That(d.MgNr, Is.EqualTo(102));
Assert.That(p.SortId, Is.EqualTo("ZW"));
Assert.That(p.AttrId, Is.Not.Null);
Assert.That(p.CultId, Is.Not.Null);
Assert.That(p.Kmw, Is.EqualTo(15.9));
Assert.That(p.Oe, Is.EqualTo(78));
Assert.That(p.QualId, Is.EqualTo("QUW"));
Assert.That(p.Weight, Is.EqualTo(3456));
Assert.That(p.IsNetWeight, Is.True);
Assert.That(p.IsManualWeighing, Is.False);
Assert.That(p.WeighingData, Is.EqualTo("{}"));
Assert.That(p.HkId, Is.EqualTo("WLNO"));
Assert.That(p.Modifiers.Count(), Is.EqualTo(1));
});
vm = new DeliveryAdminViewModel();
await InitViewModel(vm);
Assert.DoesNotThrow(() => {
vm.FillInputs(d);
vm.FillInputs(p);
});
Assert.Multiple(() => {
Assert.That(vm.LsNr, Is.EqualTo("20221002X001"));
Assert.That(vm.Date, Is.EqualTo("02.10.2022"));
Assert.That(vm.Branch?.ZwstId, Is.EqualTo("X"));
Assert.That(vm.MgNr, Is.EqualTo(102));
Assert.That(vm.SortId, Is.EqualTo("ZW"));
Assert.That(vm.WineAttr?.AttrId, Is.Not.Null);
Assert.That(vm.WineCult?.CultId, Is.Not.Null);
Assert.That(vm.GradationKmw, Is.EqualTo(15.9));
Assert.That(vm.WineQualityLevel?.QualId, Is.EqualTo("QUW"));
Assert.That(vm.Weight, Is.EqualTo(3456));
Assert.That(vm.IsNetWeight, Is.True);
Assert.That(vm.IsManualWeighing, Is.False);
Assert.That(vm.WeighingData, Is.EqualTo("{}"));
Assert.That(vm.WineOrigin?.HkId, Is.EqualTo("WLNO"));
Assert.That(vm.Modifiers, Has.Count.EqualTo(1));
});
}
[Test]
public async Task TestCreate_03_TwoParts() {
var vm = new DeliveryAdminViewModel();
await InitViewModel(vm);
vm.Date = "03.10.2022";
vm.Branch = vm.BranchSource.First();
vm.MgNr = 101;
vm.Member = vm.MemberSource.First(m => m.MgNr == vm.MgNr);
vm.SortId = "GV";
vm.WineVar = vm.WineVarSource.First(v => v.SortId == vm.SortId);
vm.GradationKmw = 15.0;
vm.GradationOe = 73;
vm.WineQualityLevel = vm.WineQualityLevelSource.First(l => l.QualId == "QUW");
vm.Weight = 1234;
vm.IsManualWeighing = true;
vm.IsNetWeight = true;
vm.WineOrigin = vm.WineOriginSource.First(o => o.HkId == "WLNO");
var p1 = await vm.UpdateDeliveryPart(2022, null, null, false, false, true);
Assert.That(p1.Delivery.LsNr, Is.EqualTo("20221003X001"));
vm.FillInputs(p1.Delivery);
vm.SortId = "WR";
vm.WineVar = vm.WineVarSource.First(v => v.SortId == vm.SortId);
vm.GradationKmw = 18.0;
vm.GradationOe = 89;
vm.WineQualityLevel = vm.WineQualityLevelSource.First(l => l.QualId == "KAB");
vm.Weight = 2345;
var p2 = await vm.UpdateDeliveryPart(p1.Year, p1.DId, null, false, false, true);
Assert.That(p2.Delivery.LsNr, Is.EqualTo("20221003X001"));
var d = await GetDelivery("20221003X001");
Assert.That(d, Is.Not.Null);
Assert.Multiple(() => {
Assert.That(d.Parts, Has.Count.EqualTo(2));
Assert.That(d.MgNr, Is.EqualTo(101));
});
var p = d.Parts.First();
Assert.That(p, Is.Not.Null);
Assert.Multiple(() => {
Assert.That(p.DPNr, Is.EqualTo(1));
Assert.That(p.SortId, Is.EqualTo("GV"));
});
p = d.Parts.Skip(1).First();
Assert.That(p, Is.Not.Null);
Assert.Multiple(() => {
Assert.That(p.DPNr, Is.EqualTo(2));
Assert.That(p.SortId, Is.EqualTo("WR"));
});
}
[Test]
public async Task TestCreate_04_ChangeMember() {
var vm = new DeliveryAdminViewModel();
await InitViewModel(vm);
vm.Date = "04.10.2022";
vm.Branch = vm.BranchSource.First();
vm.MgNr = 101;
vm.Member = vm.MemberSource.First(m => m.MgNr == vm.MgNr);
vm.SortId = "GV";
vm.WineVar = vm.WineVarSource.First(v => v.SortId == vm.SortId);
vm.GradationKmw = 15.0;
vm.GradationOe = 73;
vm.WineQualityLevel = vm.WineQualityLevelSource.First(l => l.QualId == "QUW");
vm.Weight = 1234;
vm.IsManualWeighing = true;
vm.IsNetWeight = true;
vm.WineOrigin = vm.WineOriginSource.First(o => o.HkId == "WLNO");
var p1 = await vm.UpdateDeliveryPart(2022, null, null, false, false, true);
Assert.That(p1.Delivery.LsNr, Is.EqualTo("20221004X001"));
vm.FillInputs(p1.Delivery);
vm.MgNr = 102;
vm.Member = vm.MemberSource.First(m => m.MgNr == vm.MgNr);
vm.SortId = "GV";
vm.WineVar = vm.WineVarSource.First(v => v.SortId == vm.SortId);
vm.GradationKmw = 15.0;
vm.GradationOe = 73;
vm.WineQualityLevel = vm.WineQualityLevelSource.First(l => l.QualId == "QUW");
vm.Weight = 1234;
vm.IsManualWeighing = true;
vm.IsNetWeight = true;
vm.WineOrigin = vm.WineOriginSource.First(o => o.HkId == "WLNO");
var p2 = await vm.UpdateDeliveryPart(p1.Year, p1.DId, null, false, false, true);
Assert.That(p2.Delivery.LsNr, Is.EqualTo("20221004X001"));
var d = await GetDelivery("20221004X001");
Assert.That(d, Is.Not.Null);
Assert.Multiple(() => {
Assert.That(d.Parts, Has.Count.EqualTo(2));
Assert.That(d.MgNr, Is.EqualTo(102));
});
}
[Test]
public async Task TestCreate_05_LNrChanged() {
var vm = new DeliveryAdminViewModel();
await InitViewModel(vm);
vm.Date = "29.09.2022";
vm.Branch = vm.BranchSource.First();
vm.LsNr = "20220929X001"; // "old" LNr, simulated change in DB
vm.MgNr = 101;
vm.Member = vm.MemberSource.First(m => m.MgNr == vm.MgNr);
vm.SortId = "GV";
vm.WineVar = vm.WineVarSource.First(v => v.SortId == vm.SortId);
vm.GradationKmw = 15.0;
vm.GradationOe = 73;
vm.WineQualityLevel = vm.WineQualityLevelSource.First(l => l.QualId == "QUW");
vm.Weight = 1234;
vm.IsManualWeighing = true;
vm.IsNetWeight = true;
vm.WineOrigin = vm.WineOriginSource.First(o => o.HkId == "WLNO");
var p1 = await vm.UpdateDeliveryPart(2022, null, null, false, false, true);
Assert.That(p1.Delivery.LsNr, Is.EqualTo("20220929X002"));
var d = GetDelivery("20220929X002");
Assert.That(d, Is.Not.Null);
}
[Test]
public async Task TestUpdate_01_Simple() {
var vm = new DeliveryAdminViewModel();
await InitViewModel(vm);
var d = await GetDelivery("20231010X001");
Assert.That(d, Is.Not.Null);
var p = d.Parts.First();
Assert.That(p, Is.Not.Null);
Assert.DoesNotThrow(() => {
vm.FillInputs(d);
vm.FillInputs(p);
});
vm.SortId = "WR";
vm.WineVar = vm.WineVarSource.First(v => v.SortId == vm.SortId);
vm.GradationKmw = 15.9;
vm.GradationOe = 79;
Assert.DoesNotThrowAsync(async () => await DeliveryService.UpdateDeliveryPart(vm, p.Year, p.DId, p.DPNr, false, false, true));
d = await GetDelivery("20231010X001");
Assert.That(d, Is.Not.Null);
p = d.Parts.First();
Assert.That(p, Is.Not.Null);
vm = new DeliveryAdminViewModel();
await InitViewModel(vm);
Assert.DoesNotThrow(() => {
vm.FillInputs(d);
vm.FillInputs(p);
});
Assert.Multiple(() => {
Assert.That(vm.SortId, Is.EqualTo("WR"));
Assert.That(vm.GradationKmw, Is.EqualTo(15.9));
});
}
[Test]
public async Task TestUpdate_02_Member() {
var vm = new DeliveryAdminViewModel();
await InitViewModel(vm);
var d = await GetDelivery("20231010X002");
Assert.That(d, Is.Not.Null);
var p = d.Parts.First();
Assert.That(p, Is.Not.Null);
Assert.DoesNotThrow(() => {
vm.FillInputs(d);
vm.FillInputs(p);
});
Assert.That(d.MgNr, Is.EqualTo(101));
vm.SortId = "GV";
vm.WineVar = vm.WineVarSource.First(v => v.SortId == vm.SortId);
vm.MgNr = 102;
vm.Member = vm.MemberSource.First(m => m.MgNr == vm.MgNr);
Assert.DoesNotThrowAsync(async () => await DeliveryService.UpdateDeliveryPart(vm, p.Year, p.DId, p.DPNr, false, false, true));
d = await GetDelivery("20231010X002");
Assert.That(d, Is.Not.Null);
Assert.That(d.MgNr, Is.EqualTo(102));
}
[Test]
public async Task TestUpdate_03_DateAndTime() {
var vm = new DeliveryAdminViewModel();
await InitViewModel(vm);
var d = await GetDelivery("20231015X001");
Assert.That(d, Is.Null);
d = await GetDelivery("20231010X003");
Assert.That(d, Is.Not.Null);
var p = d.Parts.First();
Assert.That(p, Is.Not.Null);
Assert.DoesNotThrow(() => {
vm.FillInputs(d);
vm.FillInputs(p);
});
Assert.That(d.MgNr, Is.EqualTo(101));
vm.SortId = "GV";
vm.WineVar = vm.WineVarSource.First(v => v.SortId == vm.SortId);
vm.Date = "15.10.2023";
vm.Time = "12:00";
Assert.DoesNotThrowAsync(async () => await DeliveryService.UpdateDeliveryPart(vm, p.Year, p.DId, p.DPNr, true, true, false));
d = await GetDelivery("20231010X003");
Assert.That(d, Is.Null);
d = await GetDelivery("20231015X001");
Assert.That(d, Is.Not.Null);
}
[Test]
public async Task TestSplit_01_Depreciate_One() {
var d = await GetDelivery("20231001X001");
Assert.That(d, Is.Not.Null);
Assert.Multiple(() => {
var ps = GetParts(d);
Assert.That(ps, Has.Length.EqualTo(3));
Assert.That(ps[0].Weight, Is.EqualTo(1000));
Assert.That(ps[0].QualId, Is.Not.EqualTo("WEI"));
Assert.That(ps[1].QualId, Is.Not.EqualTo("WEI"));
Assert.That(ps[2].QualId, Is.Not.EqualTo("WEI"));
});
Assert.DoesNotThrowAsync(async () => await DeliveryService.DepreciateDelivery(d.Year, d.DId, [1000, 0, 0]));
d = await GetDelivery("20231001X001");
Assert.That(d, Is.Not.Null);
Assert.Multiple(() => {
var ps = GetParts(d);
Assert.That(ps, Has.Length.EqualTo(3));
Assert.That(ps[0].Weight, Is.EqualTo(1000));
Assert.That(ps[0].QualId, Is.EqualTo("WEI"));
Assert.That(ps[1].QualId, Is.Not.EqualTo("WEI"));
Assert.That(ps[2].QualId, Is.Not.EqualTo("WEI"));
});
}
[Test]
public async Task TestSplit_02_Depreciate_Partial() {
var d = await GetDelivery("20231001X002");
Assert.That(d, Is.Not.Null);
Assert.Multiple(() => {
var ps = GetParts(d);
Assert.That(ps, Has.Length.EqualTo(3));
Assert.That(ps[0].Weight, Is.EqualTo(1000));
Assert.That(ps[0].QualId, Is.Not.EqualTo("WEI"));
Assert.That(ps[1].QualId, Is.Not.EqualTo("WEI"));
Assert.That(ps[2].QualId, Is.Not.EqualTo("WEI"));
});
Assert.DoesNotThrowAsync(async () => await DeliveryService.DepreciateDelivery(d.Year, d.DId, [600, 0, 0]));
d = await GetDelivery("20231001X002");
Assert.That(d, Is.Not.Null);
Assert.Multiple(() => {
var ps = GetParts(d);
Assert.That(ps, Has.Length.EqualTo(4));
Assert.That(ps[0].Weight, Is.EqualTo(400));
Assert.That(ps[0].QualId, Is.Not.EqualTo("WEI"));
Assert.That(ps[1].QualId, Is.Not.EqualTo("WEI"));
Assert.That(ps[2].QualId, Is.Not.EqualTo("WEI"));
Assert.That(ps[3].Weight, Is.EqualTo(600));
Assert.That(ps[3].QualId, Is.EqualTo("WEI"));
});
}
[Test]
public async Task TestSplit_03_Depreciate_Mixed() {
var d = await GetDelivery("20231001X003");
Assert.That(d, Is.Not.Null);
Assert.Multiple(() => {
var ps = GetParts(d);
Assert.That(ps, Has.Length.EqualTo(3));
Assert.That(ps[0].Weight, Is.EqualTo(1000));
Assert.That(ps[0].QualId, Is.Not.EqualTo("WEI"));
Assert.That(ps[1].Weight, Is.EqualTo(1000));
Assert.That(ps[1].QualId, Is.Not.EqualTo("WEI"));
Assert.That(ps[2].QualId, Is.Not.EqualTo("WEI"));
});
Assert.DoesNotThrowAsync(async () => await DeliveryService.DepreciateDelivery(d.Year, d.DId, [1000, 700, -5]));
d = await GetDelivery("20231001X003");
Assert.That(d, Is.Not.Null);
Assert.Multiple(() => {
var ps = GetParts(d);
Assert.That(ps, Has.Length.EqualTo(4));
Assert.That(ps[0].Weight, Is.EqualTo(1000));
Assert.That(ps[0].QualId, Is.EqualTo("WEI"));
Assert.That(ps[1].Weight, Is.EqualTo(300));
Assert.That(ps[1].QualId, Is.Not.EqualTo("WEI"));
Assert.That(ps[2].Weight, Is.EqualTo(1000));
Assert.That(ps[2].QualId, Is.Not.EqualTo("WEI"));
Assert.That(ps[3].Weight, Is.EqualTo(700));
Assert.That(ps[3].QualId, Is.EqualTo("WEI"));
});
}
[Test]
public async Task TestSplit_04_Depreciate_Complete() {
var d = await GetDelivery("20231001X004");
Assert.That(d, Is.Not.Null);
Assert.Multiple(() => {
var ps = GetParts(d);
Assert.That(ps, Has.Length.EqualTo(3));
Assert.That(ps[0].Weight, Is.EqualTo(1000));
Assert.That(ps[0].QualId, Is.Not.EqualTo("WEI"));
Assert.That(ps[1].Weight, Is.EqualTo(1000));
Assert.That(ps[1].QualId, Is.Not.EqualTo("WEI"));
Assert.That(ps[2].Weight, Is.EqualTo(1000));
Assert.That(ps[2].QualId, Is.Not.EqualTo("WEI"));
});
Assert.DoesNotThrowAsync(async () => await DeliveryService.DepreciateDelivery(d.Year, d.DId, [1000, 1100, int.MaxValue]));
d = await GetDelivery("20231001X004");
Assert.That(d, Is.Not.Null);
Assert.Multiple(() => {
var ps = GetParts(d);
Assert.That(ps, Has.Length.EqualTo(3));
Assert.That(ps[0].Weight, Is.EqualTo(1000));
Assert.That(ps[0].QualId, Is.EqualTo("WEI"));
Assert.That(ps[1].Weight, Is.EqualTo(1000));
Assert.That(ps[1].QualId, Is.EqualTo("WEI"));
Assert.That(ps[2].Weight, Is.EqualTo(1000));
Assert.That(ps[2].QualId, Is.EqualTo("WEI"));
});
}
[Test]
public async Task TestSplit_05_OtherMember_One() {
var d1 = await GetDelivery("20231002X001");
var d2 = await GetDelivery("20231002X002");
Assert.Multiple(() => {
Assert.That(d1, Is.Not.Null);
Assert.That(d2, Is.Null);
});
Assert.Multiple(() => {
var ps1 = GetParts(d1);
Assert.That(d1.MgNr, Is.EqualTo(101));
Assert.That(ps1, Has.Length.EqualTo(3));
Assert.That(ps1[0].Weight, Is.EqualTo(1000));
Assert.That(ps1[1].Weight, Is.EqualTo(1000));
Assert.That(ps1[2].Weight, Is.EqualTo(1000));
});
Assert.DoesNotThrowAsync(async () => await DeliveryService.SplitDeliveryToMember(d1.Year, d1.DId, [1000, 0, 0], 102));
d1 = await GetDelivery("20231002X001");
d2 = await GetDelivery("20231002X002");
Assert.Multiple(() => {
Assert.That(d1, Is.Not.Null);
Assert.That(d2, Is.Not.Null);
});
Assert.Multiple(() => {
var ps1 = GetParts(d1);
var ps2 = GetParts(d2);
Assert.That(d1.MgNr, Is.EqualTo(101));
Assert.That(d2.MgNr, Is.EqualTo(102));
Assert.That(ps1, Has.Length.EqualTo(2));
Assert.That(ps1[0].DPNr, Is.EqualTo(2));
Assert.That(ps1[0].Weight, Is.EqualTo(1000));
Assert.That(ps1[1].DPNr, Is.EqualTo(3));
Assert.That(ps1[1].Weight, Is.EqualTo(1000));
Assert.That(ps2, Has.Length.EqualTo(1));
Assert.That(ps2[0].DPNr, Is.EqualTo(1));
Assert.That(ps2[0].Weight, Is.EqualTo(1000));
});
}
[Test]
public async Task TestSplit_06_OtherMember_Partial() {
var d1 = await GetDelivery("20231003X001");
var d2 = await GetDelivery("20231003X002");
Assert.Multiple(() => {
Assert.That(d1, Is.Not.Null);
Assert.That(d2, Is.Null);
});
Assert.Multiple(() => {
var ps1 = GetParts(d1);
Assert.That(d1.MgNr, Is.EqualTo(101));
Assert.That(ps1, Has.Length.EqualTo(3));
Assert.That(ps1[0].Weight, Is.EqualTo(1000));
Assert.That(ps1[1].Weight, Is.EqualTo(1000));
Assert.That(ps1[2].Weight, Is.EqualTo(1000));
});
Assert.DoesNotThrowAsync(async () => await DeliveryService.SplitDeliveryToMember(d1.Year, d1.DId, [400, -1, -2], 102));
d1 = await GetDelivery("20231003X001");
d2 = await GetDelivery("20231003X002");
Assert.Multiple(() => {
Assert.That(d1, Is.Not.Null);
Assert.That(d2, Is.Not.Null);
});
Assert.Multiple(() => {
var ps1 = GetParts(d1);
var ps2 = GetParts(d2);
Assert.That(d1.MgNr, Is.EqualTo(101));
Assert.That(d2.MgNr, Is.EqualTo(102));
Assert.That(ps1, Has.Length.EqualTo(3));
Assert.That(ps1[0].Weight, Is.EqualTo(600));
Assert.That(ps1[1].Weight, Is.EqualTo(1000));
Assert.That(ps1[2].Weight, Is.EqualTo(1000));
Assert.That(ps2, Has.Length.EqualTo(1));
Assert.That(ps2[0].Weight, Is.EqualTo(400));
});
}
[Test]
public async Task TestSplit_07_OtherMember_Mixed() {
var d1 = await GetDelivery("20231004X001");
var d2 = await GetDelivery("20231004X002");
Assert.Multiple(() => {
Assert.That(d1, Is.Not.Null);
Assert.That(d2, Is.Null);
});
Assert.Multiple(() => {
var ps1 = GetParts(d1);
Assert.That(d1.MgNr, Is.EqualTo(101));
Assert.That(ps1, Has.Length.EqualTo(3));
Assert.That(ps1[0].Weight, Is.EqualTo(1000));
Assert.That(ps1[1].Weight, Is.EqualTo(1000));
Assert.That(ps1[2].Weight, Is.EqualTo(1000));
});
Assert.DoesNotThrowAsync(async () => await DeliveryService.SplitDeliveryToMember(d1.Year, d1.DId, [200, 1000, int.MinValue], 102));
d1 = await GetDelivery("20231004X001");
d2 = await GetDelivery("20231004X002");
Assert.Multiple(() => {
Assert.That(d1, Is.Not.Null);
Assert.That(d2, Is.Not.Null);
});
Assert.Multiple(() => {
var ps1 = GetParts(d1);
var ps2 = GetParts(d2);
Assert.That(d1.MgNr, Is.EqualTo(101));
Assert.That(d2.MgNr, Is.EqualTo(102));
Assert.That(ps1, Has.Length.EqualTo(2));
Assert.That(ps1[0].DPNr, Is.EqualTo(1));
Assert.That(ps1[0].Weight, Is.EqualTo(800));
Assert.That(ps1[1].DPNr, Is.EqualTo(3));
Assert.That(ps1[1].Weight, Is.EqualTo(1000));
Assert.That(ps2, Has.Length.EqualTo(2));
Assert.That(ps2[0].DPNr, Is.EqualTo(1));
Assert.That(ps2[0].Weight, Is.EqualTo(200));
Assert.That(ps2[1].DPNr, Is.EqualTo(2));
Assert.That(ps2[1].Weight, Is.EqualTo(1000));
});
}
[Test]
public async Task TestSplit_08_OtherMember_Complete() {
var d1 = await GetDelivery("20231005X001");
var d2 = await GetDelivery("20231005X002");
Assert.Multiple(() => {
Assert.That(d1, Is.Not.Null);
Assert.That(d2, Is.Null);
});
Assert.Multiple(() => {
var ps1 = GetParts(d1);
Assert.That(d1.MgNr, Is.EqualTo(101));
Assert.That(ps1, Has.Length.EqualTo(3));
Assert.That(ps1[0].Weight, Is.EqualTo(1000));
Assert.That(ps1[1].Weight, Is.EqualTo(1000));
Assert.That(ps1[2].Weight, Is.EqualTo(1000));
});
Assert.DoesNotThrowAsync(async () => await DeliveryService.SplitDeliveryToMember(d1.Year, d1.DId, [1000, int.MaxValue, 1100], 102));
d1 = await GetDelivery("20231005X001");
d2 = await GetDelivery("20231005X002");
Assert.Multiple(() => {
Assert.That(d1, Is.Null);
Assert.That(d2, Is.Not.Null);
});
Assert.Multiple(() => {
var ps2 = GetParts(d2);
Assert.That(d2.MgNr, Is.EqualTo(102));
Assert.That(ps2, Has.Length.EqualTo(3));
Assert.That(ps2[0].Weight, Is.EqualTo(1000));
Assert.That(ps2[1].Weight, Is.EqualTo(1000));
Assert.That(ps2[2].Weight, Is.EqualTo(1000));
});
}
[Test]
public async Task TestSplit_09_OtherDelivery_One() {
var d1 = await GetDelivery("20231006X001");
var d2 = await GetDelivery("20231006X002");
Assert.Multiple(() => {
Assert.That(d1, Is.Not.Null);
Assert.That(d2, Is.Not.Null);
});
Assert.Multiple(() => {
var ps1 = GetParts(d1);
var ps2 = GetParts(d2);
Assert.That(ps1, Has.Length.EqualTo(3));
Assert.That(ps1[0].Weight, Is.EqualTo(1000));
Assert.That(ps1[1].Weight, Is.EqualTo(1000));
Assert.That(ps1[2].Weight, Is.EqualTo(1000));
Assert.That(ps2, Has.Length.EqualTo(1));
Assert.That(ps2[0].Weight, Is.EqualTo(1000));
});
Assert.DoesNotThrowAsync(async () => await DeliveryService.SplitDeliveryToLsNr(d1.Year, d1.DId, [0, 1000, -4], d2.LsNr));
d1 = await GetDelivery("20231006X001");
d2 = await GetDelivery("20231006X002");
Assert.Multiple(() => {
Assert.That(d1, Is.Not.Null);
Assert.That(d2, Is.Not.Null);
});
Assert.Multiple(() => {
var ps1 = GetParts(d1);
var ps2 = GetParts(d2);
Assert.That(ps1, Has.Length.EqualTo(2));
Assert.That(ps1[0].DPNr, Is.EqualTo(1));
Assert.That(ps1[0].Weight, Is.EqualTo(1000));
Assert.That(ps1[1].DPNr, Is.EqualTo(3));
Assert.That(ps1[1].Weight, Is.EqualTo(1000));
Assert.That(ps2, Has.Length.EqualTo(2));
Assert.That(ps2[0].Weight, Is.EqualTo(1000));
Assert.That(ps2[1].Weight, Is.EqualTo(1000));
});
}
[Test]
public async Task TestSplit_10_OtherDelivery_Partial() {
var d1 = await GetDelivery("20231007X001");
var d2 = await GetDelivery("20231007X002");
Assert.Multiple(() => {
Assert.That(d1, Is.Not.Null);
Assert.That(d2, Is.Not.Null);
});
Assert.Multiple(() => {
var ps1 = GetParts(d1);
var ps2 = GetParts(d2);
Assert.That(ps1, Has.Length.EqualTo(3));
Assert.That(ps1[0].Weight, Is.EqualTo(1000));
Assert.That(ps1[1].Weight, Is.EqualTo(1000));
Assert.That(ps1[2].Weight, Is.EqualTo(1000));
Assert.That(ps2, Has.Length.EqualTo(1));
Assert.That(ps2[0].Weight, Is.EqualTo(1000));
});
Assert.DoesNotThrowAsync(async () => await DeliveryService.SplitDeliveryToLsNr(d1.Year, d1.DId, [0, 300, int.MinValue], d2.LsNr));
d1 = await GetDelivery("20231007X001");
d2 = await GetDelivery("20231007X002");
Assert.Multiple(() => {
Assert.That(d1, Is.Not.Null);
Assert.That(d2, Is.Not.Null);
});
Assert.Multiple(() => {
var ps1 = GetParts(d1);
var ps2 = GetParts(d2);
Assert.That(ps1, Has.Length.EqualTo(3));
Assert.That(ps1[0].Weight, Is.EqualTo(1000));
Assert.That(ps1[1].Weight, Is.EqualTo(700));
Assert.That(ps1[2].Weight, Is.EqualTo(1000));
Assert.That(ps2, Has.Length.EqualTo(2));
Assert.That(ps2[0].Weight, Is.EqualTo(1000));
Assert.That(ps2[1].Weight, Is.EqualTo(300));
});
}
[Test]
public async Task TestSplit_11_OtherDelivery_Mixed() {
var d1 = await GetDelivery("20231008X001");
var d2 = await GetDelivery("20231008X002");
Assert.Multiple(() => {
Assert.That(d1, Is.Not.Null);
Assert.That(d2, Is.Not.Null);
});
Assert.Multiple(() => {
var ps1 = GetParts(d1);
var ps2 = GetParts(d2);
Assert.That(ps1, Has.Length.EqualTo(3));
Assert.That(ps1[0].Weight, Is.EqualTo(1000));
Assert.That(ps1[1].Weight, Is.EqualTo(1000));
Assert.That(ps1[2].Weight, Is.EqualTo(1000));
Assert.That(ps2, Has.Length.EqualTo(1));
Assert.That(ps2[0].Weight, Is.EqualTo(1000));
});
Assert.DoesNotThrowAsync(async () => await DeliveryService.SplitDeliveryToLsNr(d1.Year, d1.DId, [850, 1000, -4], d2.LsNr));
d1 = await GetDelivery("20231008X001");
d2 = await GetDelivery("20231008X002");
Assert.Multiple(() => {
Assert.That(d1, Is.Not.Null);
Assert.That(d2, Is.Not.Null);
});
Assert.Multiple(() => {
var ps1 = GetParts(d1);
var ps2 = GetParts(d2);
Assert.That(ps1, Has.Length.EqualTo(2));
Assert.That(ps1[0].DPNr, Is.EqualTo(1));
Assert.That(ps1[0].Weight, Is.EqualTo(150));
Assert.That(ps1[1].DPNr, Is.EqualTo(3));
Assert.That(ps1[1].Weight, Is.EqualTo(1000));
Assert.That(ps2, Has.Length.EqualTo(3));
Assert.That(ps2[0].Weight, Is.EqualTo(1000));
Assert.That(ps2[1].Weight, Is.EqualTo(850));
Assert.That(ps2[2].Weight, Is.EqualTo(1000));
});
}
[Test]
public async Task TestSplit_12_OtherDelivery_Complete() {
var d1 = await GetDelivery("20231009X001");
var d2 = await GetDelivery("20231009X002");
Assert.Multiple(() => {
Assert.That(d1, Is.Not.Null);
Assert.That(d2, Is.Not.Null);
});
Assert.Multiple(() => {
var ps1 = GetParts(d1);
var ps2 = GetParts(d2);
Assert.That(ps1, Has.Length.EqualTo(3));
Assert.That(ps1[0].Weight, Is.EqualTo(1000));
Assert.That(ps1[1].Weight, Is.EqualTo(1000));
Assert.That(ps1[2].Weight, Is.EqualTo(1000));
Assert.That(ps2, Has.Length.EqualTo(1));
Assert.That(ps2[0].Weight, Is.EqualTo(1000));
});
Assert.DoesNotThrowAsync(async () => await DeliveryService.SplitDeliveryToLsNr(d1.Year, d1.DId, [1200, int.MaxValue, 1000], d2.LsNr));
d1 = await GetDelivery("20231009X001");
d2 = await GetDelivery("20231009X002");
Assert.Multiple(() => {
Assert.That(d1, Is.Null);
Assert.That(d2, Is.Not.Null);
});
Assert.Multiple(() => {
var ps2 = GetParts(d2);
Assert.That(ps2, Has.Length.EqualTo(4));
Assert.That(ps2[0].Weight, Is.EqualTo(1000));
Assert.That(ps2[1].Weight, Is.EqualTo(1000));
Assert.That(ps2[2].Weight, Is.EqualTo(1000));
Assert.That(ps2[3].Weight, Is.EqualTo(1000));
});
}
[Test]
public async Task TestDelete_01_Normal() {
using (var ctx = new AppDbContext()) {
Assert.That(await ctx.Deliveries.FindAsync(2022, 2), Is.Not.Null);
}
Assert.DoesNotThrowAsync(async () => await DeliveryService.DeleteDelivery("20220930X001"));
using (var ctx = new AppDbContext()) {
Assert.That(await ctx.Deliveries.FindAsync(2022, 2), Is.Null);
}
}
}
}

View File

@ -0,0 +1,361 @@
using Elwig.Helpers;
using Elwig.Models.Entities;
using Elwig.Services;
using Elwig.ViewModels;
using Microsoft.EntityFrameworkCore;
namespace Tests.ServiceTests {
[TestFixture]
public class MemberServiceTest {
private static async Task InitViewModel(MemberAdminViewModel vm) {
using var ctx = new AppDbContext();
vm.BranchSource = await ctx.Branches.ToListAsync();
vm.DefaultKgSource = await ctx.Katastralgemeinden.ToListAsync();
vm.OrtSource = await ctx.PlzDestinations.Include(p => p.Ort).ToListAsync();
vm.BillingOrtSource = await ctx.PlzDestinations.Include(p => p.Ort).ToListAsync();
}
[Test]
public async Task TestCreate_01_Minimal() {
var vm = new MemberAdminViewModel();
await InitViewModel(vm);
await vm.InitInputs();
vm.Name = "Neuling";
vm.GivenName = "Nadine";
vm.Address = "Neubaugasse 1";
vm.Plz = 2120;
vm.Ort = vm.OrtSource.First(d => d.Ort.Name == "Wolkersdorf im Weinviertel");
vm.BusinessShares = 1;
vm.DefaultKg = vm.DefaultKgSource.First(k => k.Name == "Wolkersdorf");
Assert.That(vm.MgNr, Is.EqualTo(205));
using (var ctx = new AppDbContext()) {
Assert.That(await ctx.Members.FindAsync(205), Is.Null);
}
Assert.DoesNotThrowAsync(async () => await vm.UpdateMember(null));
Member? m;
using (var ctx = new AppDbContext()) {
m = await ctx.Members
.Where(m => m.MgNr == vm.MgNr)
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.DefaultWbKg!.AtKg)
.Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers)
.AsSplitQuery()
.FirstOrDefaultAsync();
}
Assert.That(m, Is.Not.Null);
Assert.Multiple(() => {
Assert.That(m.MgNr, Is.EqualTo(205));
Assert.That(m.Name, Is.EqualTo("Neuling"));
Assert.That(m.GivenName, Is.EqualTo("Nadine"));
Assert.That(m.Address, Is.EqualTo("Neubaugasse 1"));
Assert.That(m.PostalDest.AtPlz?.Plz, Is.EqualTo(2120));
Assert.That(m.PostalDest.AtPlz?.Ort.Name, Is.EqualTo("Wolkersdorf im Weinviertel"));
Assert.That(m.BusinessShares, Is.EqualTo(1));
Assert.That(m.DefaultKg?.Name, Is.EqualTo("Wolkersdorf"));
});
vm = new MemberAdminViewModel();
await InitViewModel(vm);
Assert.DoesNotThrow(() => vm.FillInputs(m));
Assert.Multiple(() => {
Assert.That(vm.MgNr, Is.EqualTo(205));
Assert.That(vm.Name, Is.EqualTo("Neuling"));
Assert.That(vm.GivenName, Is.EqualTo("Nadine"));
Assert.That(vm.Address, Is.EqualTo("Neubaugasse 1"));
Assert.That(vm.Plz, Is.EqualTo(2120));
Assert.That(vm.Ort?.Ort.Name, Is.EqualTo("Wolkersdorf im Weinviertel"));
Assert.That(vm.BusinessShares, Is.EqualTo(1));
Assert.That(vm.DefaultKg?.Name, Is.EqualTo("Wolkersdorf"));
});
}
[Test]
public async Task TestCreate_02_Full() {
var vm = new MemberAdminViewModel();
await InitViewModel(vm);
await vm.InitInputs();
vm.MgNr = 999;
vm.IsJuridicalPerson = true;
vm.Name = "Neue GmbH";
vm.ForTheAttentionOf = "Norbert Neuling";
vm.Address = "Neuegasse 2";
vm.Plz = 2120;
vm.Ort = vm.OrtSource.First(d => d.Ort.Name == "Wolkersdorf im Weinviertel");
vm.EmailAddresses[0] = "neue.gmbh@mail.com";
vm.EmailAddresses[1] = "norbert.neuling@mail.com";
vm.PhoneNrs[0] = new(0, "+43 2245 9876", "Büro");
vm.PhoneNrs[1] = new(1, "+43 664 123456789", "Hr. Neuling");
vm.PhoneNrs[2] = new(2, "+43 2245 9876-2", null);
vm.Iban = "AT97 1234 5678 9012 3460";
vm.Bic = "RLNWATWWWDF";
vm.UstIdNr = "ATU12345693";
vm.LfbisNr = "0123498";
vm.IsBuchführend = true;
vm.IsOrganic = true;
vm.BillingName = "Neue Holding AG";
vm.BillingAddress = "Neuegasse 3";
vm.BillingPlz = 2120;
vm.BillingOrt = vm.BillingOrtSource.First(d => d.Ort.Name == "Wolkersdorf im Weinviertel");
vm.BusinessShares = 10;
vm.AccountingNr = "330999";
vm.DefaultKg = vm.DefaultKgSource.First(k => k.Name == "Wolkersdorf");
vm.Comment = "Ich bin eine Anmerkung";
vm.ContactViaPost = true;
vm.ContactViaEmail = true;
vm.IsVollLieferant = true;
vm.IsFunktionär = true;
using (var ctx = new AppDbContext()) {
Assert.That(await ctx.Members.FindAsync(999), Is.Null);
}
Assert.DoesNotThrowAsync(async () => await vm.UpdateMember(null));
Member? m;
using (var ctx = new AppDbContext()) {
m = await ctx.Members
.Where(m => m.MgNr == vm.MgNr)
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.DefaultWbKg!.AtKg)
.Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers)
.AsSplitQuery()
.FirstOrDefaultAsync();
}
Assert.That(m, Is.Not.Null);
Assert.Multiple(() => {
Assert.That(m.MgNr, Is.EqualTo(999));
Assert.That(m.IsJuridicalPerson, Is.True);
Assert.That(m.Name, Is.EqualTo("Neue GmbH"));
Assert.That(m.ForTheAttentionOf, Is.EqualTo("Norbert Neuling"));
Assert.That(m.Address, Is.EqualTo("Neuegasse 2"));
Assert.That(m.PostalDest.AtPlz?.Plz, Is.EqualTo(2120));
Assert.That(m.PostalDest.AtPlz?.Ort.Name, Is.EqualTo("Wolkersdorf im Weinviertel"));
Assert.That(m.EmailAddresses.Select(a => (a.Nr, a.Address)), Is.EquivalentTo(new (int, string)[] {
(1, "neue.gmbh@mail.com"),
(2, "norbert.neuling@mail.com"),
}));
Assert.That(m.TelephoneNumbers.Select(n => (n.Nr, n.Type, n.Number, n.Comment)), Is.EquivalentTo(new (int, string, string, string?)[] {
(1, "landline", "+43 2245 9876", "Büro"),
(2, "mobile", "+43 664 123456789", "Hr. Neuling"),
(3, "fax", "+43 2245 9876-2", null),
}));
Assert.That(m.Iban, Is.EqualTo("AT971234567890123460"));
Assert.That(m.Bic, Is.EqualTo("RLNWATWWWDF"));
Assert.That(m.UstIdNr, Is.EqualTo("ATU12345693"));
Assert.That(m.LfbisNr, Is.EqualTo("0123498"));
Assert.That(m.IsBuchführend, Is.True);
Assert.That(m.IsOrganic, Is.True);
Assert.That(m.BillingAddress, Is.Not.Null);
Assert.That(m.BillingAddress?.FullName, Is.EqualTo("Neue Holding AG"));
Assert.That(m.BillingAddress?.Address, Is.EqualTo("Neuegasse 3"));
Assert.That(m.BillingAddress?.PostalDest.AtPlz?.Plz, Is.EqualTo(2120));
Assert.That(m.BillingAddress?.PostalDest.AtPlz?.Ort.Name, Is.EqualTo("Wolkersdorf im Weinviertel"));
Assert.That(m.BusinessShares, Is.EqualTo(10));
Assert.That(m.AccountingNr, Is.EqualTo("330999"));
Assert.That(m.DefaultKg?.Name, Is.EqualTo("Wolkersdorf"));
Assert.That(m.Comment, Is.EqualTo("Ich bin eine Anmerkung"));
Assert.That(m.ContactViaPost, Is.True);
Assert.That(m.ContactViaEmail, Is.True);
Assert.That(m.IsVollLieferant, Is.True);
Assert.That(m.IsFunktionär, Is.True);
});
vm = new MemberAdminViewModel();
await InitViewModel(vm);
Assert.DoesNotThrow(() => vm.FillInputs(m));
Assert.Multiple(() => {
Assert.That(vm.MgNr, Is.EqualTo(999));
Assert.That(vm.IsJuridicalPerson, Is.True);
Assert.That(vm.Name, Is.EqualTo("Neue GmbH"));
Assert.That(vm.ForTheAttentionOf, Is.EqualTo("Norbert Neuling"));
Assert.That(vm.Address, Is.EqualTo("Neuegasse 2"));
Assert.That(vm.Plz, Is.EqualTo(2120));
Assert.That(vm.Ort?.Ort.Name, Is.EqualTo("Wolkersdorf im Weinviertel"));
Assert.That(vm.EmailAddresses, Is.EquivalentTo(new string?[] {
"neue.gmbh@mail.com",
"norbert.neuling@mail.com",
null, null, null, null, null, null, null
}));
Assert.That(vm.PhoneNrs, Is.EquivalentTo(new MemberAdminViewModel.PhoneNr?[] {
new(0, "+43 2245 9876", "Büro"),
new(1, "+43 664 123456789", "Hr. Neuling"),
new(2, "+43 2245 9876-2", null),
new(), new(), new(), new(), new(), new()
}));
Assert.That(vm.Iban, Is.EqualTo("AT971234567890123460"));
Assert.That(vm.Bic, Is.EqualTo("RLNWATWWWDF"));
Assert.That(vm.UstIdNr, Is.EqualTo("ATU12345693"));
Assert.That(vm.LfbisNr, Is.EqualTo("0123498"));
Assert.That(vm.IsBuchführend, Is.True);
Assert.That(vm.IsOrganic, Is.True);
Assert.That(vm.BillingName, Is.EqualTo("Neue Holding AG"));
Assert.That(vm.BillingAddress, Is.EqualTo("Neuegasse 3"));
Assert.That(vm.BillingPlz, Is.EqualTo(2120));
Assert.That(vm.BillingOrt?.Ort.Name, Is.EqualTo("Wolkersdorf im Weinviertel"));
Assert.That(vm.BusinessShares, Is.EqualTo(10));
Assert.That(vm.AccountingNr, Is.EqualTo("330999"));
Assert.That(vm.DefaultKg?.Name, Is.EqualTo("Wolkersdorf"));
Assert.That(vm.Comment, Is.EqualTo("Ich bin eine Anmerkung"));
Assert.That(vm.ContactViaPost, Is.True);
Assert.That(vm.ContactViaEmail, Is.True);
Assert.That(vm.IsVollLieferant, Is.True);
Assert.That(vm.IsFunktionär, Is.True);
});
}
[Test]
public async Task TestUpdate_01_Inactive() {
var vm = new MemberAdminViewModel();
await InitViewModel(vm);
using (var ctx = new AppDbContext()) {
vm.FillInputs(await ctx.Members
.Where(m => m.MgNr == 202)
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.DefaultWbKg!.AtKg)
.Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers)
.AsSplitQuery()
.FirstAsync());
}
Assert.That(vm.IsActive, Is.True);
var exitDate = DateTime.Now;
vm.IsActive = false;
vm.ExitDate = $"{exitDate:dd.MM.yyyy}";
Assert.DoesNotThrowAsync(async () => await vm.UpdateMember(202));
Member? m;
using (var ctx = new AppDbContext()) {
m = await ctx.Members
.Where(m => m.MgNr == 202)
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.DefaultWbKg!.AtKg)
.Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers)
.AsSplitQuery()
.FirstOrDefaultAsync();
}
Assert.That(m, Is.Not.Null);
Assert.Multiple(() => {
Assert.That(m.IsActive, Is.False);
Assert.That(m.ExitDateString, Is.EqualTo($"{exitDate:yyyy-MM-dd}"));
});
vm = new MemberAdminViewModel();
await InitViewModel(vm);
Assert.DoesNotThrow(() => vm.FillInputs(m));
Assert.Multiple(() => {
Assert.That(vm.IsActive, Is.False);
Assert.That(vm.ExitDate, Is.EqualTo($"{exitDate:dd.MM.yyyy}"));
});
}
[Test]
public async Task TestUpdate_02_MgNr() {
var vm = new MemberAdminViewModel();
await InitViewModel(vm);
using (var ctx = new AppDbContext()) {
vm.FillInputs(await ctx.Members
.Where(m => m.MgNr == 203)
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.DefaultWbKg!.AtKg)
.Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers)
.AsSplitQuery()
.FirstAsync());
}
Assert.Multiple(() => {
Assert.That(vm.MgNr, Is.EqualTo(203));
Assert.That(vm.EmailAddresses[0], Is.Not.Null);
Assert.That(vm.PhoneNrs[0], Is.Not.Null);
Assert.That(vm.BillingName, Is.Not.Null);
});
vm.MgNr = 210;
Assert.DoesNotThrowAsync(async () => await vm.UpdateMember(203));
Member? m;
using (var ctx = new AppDbContext()) {
m = await ctx.Members
.Where(m => m.MgNr == 210)
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.DefaultWbKg!.AtKg)
.Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers)
.AsSplitQuery()
.FirstOrDefaultAsync();
}
Assert.That(m, Is.Not.Null);
vm = new MemberAdminViewModel();
await InitViewModel(vm);
Assert.DoesNotThrow(() => vm.FillInputs(m));
Assert.Multiple(() => {
Assert.That(vm.MgNr, Is.EqualTo(210));
Assert.That(vm.EmailAddresses[0], Is.Not.Null);
Assert.That(vm.PhoneNrs[0], Is.Not.Null);
Assert.That(vm.BillingName, Is.Not.Null);
});
}
[Test]
public async Task TestDelete_01_NoReferences() {
using (var ctx = new AppDbContext()) {
Assert.That(await ctx.Members.FindAsync(201), Is.Not.Null);
}
Assert.DoesNotThrowAsync(async () => await MemberService.DeleteMember(201, false, false, false));
using (var ctx = new AppDbContext()) {
Assert.That(await ctx.Members.FindAsync(201), Is.Null);
}
}
[Test]
public async Task TestDelete_02_AllReferences() {
using (var ctx = new AppDbContext()) {
Assert.That(await ctx.Members.FindAsync(204), Is.Not.Null);
}
for (int i = 0; i < 7; i++) {
Assert.ThrowsAsync<DbUpdateException>(async () => await MemberService.DeleteMember(204, (i & 1) != 0, (i & 2) != 0, (i & 4) != 0));
using var ctx = new AppDbContext();
Assert.That(await ctx.Members.FindAsync(204), Is.Not.Null);
}
Assert.DoesNotThrowAsync(async () => await MemberService.DeleteMember(204, true, true, true));
using (var ctx = new AppDbContext()) {
Assert.That(await ctx.Members.FindAsync(204), Is.Null);
}
}
}
}

View File

@ -0,0 +1,25 @@
using Elwig.Helpers;
using System.Reflection;
using Microsoft.Data.Sqlite;
namespace Tests.ServiceTests {
[SetUpFixture]
public class Setup {
private SqliteConnection? Connection;
[OneTimeSetUp]
public async Task SetupDatabase() {
Connection = await AppDbContext.ConnectAsync();
await AppDbContext.ExecuteEmbeddedScript(Connection, Assembly.GetExecutingAssembly(), "Tests.Resources.Sql.ServiceInsert.sql");
}
[OneTimeTearDown]
public async Task TeardownDatabase() {
if (Connection == null) return;
await AppDbContext.ExecuteEmbeddedScript(Connection, Assembly.GetExecutingAssembly(), "Tests.Resources.Sql.ServiceDelete.sql");
await Connection.DisposeAsync();
Connection = null;
}
}
}

View File

@ -171,11 +171,11 @@ namespace Tests.WeighingTests {
Thread.Sleep(100);
if (invalid) {
return ("abcd\r\n", false);
return ("abcd", false);
}
bool incr = true;
return ($" {new DateTime(2020, 9, 28, 9, 8, 0):dd.MM.yy HH:mm} {identNr,4} {weight,9}{(unit ? "lb" : "kg")} \r\n", incr);
return ($" {new DateTime(2020, 9, 28, 9, 8, 0):dd.MM.yy HH:mm} {identNr,4} {weight,9}{(unit ? "lb" : "kg")} ", incr);
}
}
}