Rename solution directory to Elwig
This commit is contained in:
28
Elwig/Helpers/AppDbContext.cs
Normal file
28
Elwig/Helpers/AppDbContext.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Elwig.Models;
|
||||
|
||||
namespace Elwig.Helpers {
|
||||
public class AppDbContext : DbContext {
|
||||
public DbSet<Country> Countries { get; set; }
|
||||
public DbSet<Member> Members { get; set; }
|
||||
public DbSet<AT_Gem> Gemeinden { get; set; }
|
||||
public DbSet<AT_Kg> Katastralgemeinden { get; set; }
|
||||
public DbSet<AT_Ort> Orte { get; set; }
|
||||
public DbSet<AT_PlzDest> Postleitzahlen { get; set; }
|
||||
public DbSet<PostalDest> PostalDestinations { get; set; }
|
||||
public DbSet<Branch> Branches { get; set; }
|
||||
public DbSet<WbKg> WbKgs { get; set; }
|
||||
public DbSet<WbRd> WbRde { get; set; }
|
||||
public DbSet<AreaCommitment> AreaCommitments { get; set; }
|
||||
public DbSet<Contract> Contracts { get; set; }
|
||||
public DbSet<WineAttr> WineAttributes { get; set; }
|
||||
public DbSet<WineCult> WineCultivations { get; set; }
|
||||
public DbSet<WineQual> WineQualities { get; set; }
|
||||
public DbSet<WineVar> WineVarieties { get; set; }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
|
||||
optionsBuilder.UseSqlite("Data Source=\"C:\\Users\\lorenz\\Desktop\\wgprod.sqlite3\"; foreign keys=true");
|
||||
optionsBuilder.UseLazyLoadingProxies();
|
||||
}
|
||||
}
|
||||
}
|
53
Elwig/Helpers/Gradation.cs
Normal file
53
Elwig/Helpers/Gradation.cs
Normal file
@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Elwig.Helpers {
|
||||
// 1 °KMW =
|
||||
// 1 °NM = kg/100L = 10g/L
|
||||
// 1 °Oe =
|
||||
// 1 °Bé =
|
||||
// 1 °Bx = g/100g (x Gramm Zucker pro 100 Gramm Flüssigkeit)
|
||||
internal class Gradation {
|
||||
/// <summary>
|
||||
/// Gradation in mg/L.
|
||||
/// </summary>
|
||||
uint mgpl;
|
||||
|
||||
public Gradation(uint mgpl) {
|
||||
this.mgpl = mgpl;
|
||||
}
|
||||
|
||||
public static double relativeDensity(double todo) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static double KmwToOe(double kmw) {
|
||||
return 0; // TODO
|
||||
}
|
||||
|
||||
public static double OeToKmw(double oe) {
|
||||
return 0; // TODO
|
||||
}
|
||||
|
||||
public static Gradation FromKmw(double kwm) {
|
||||
return new Gradation(0); // TODO
|
||||
}
|
||||
|
||||
public static Gradation FromKmw(double kmw, double t) {
|
||||
// The temperature can be ignored, because no volumetric unit is involved.
|
||||
// 1 °KMW = 1g/100g
|
||||
return FromKmw(kmw);
|
||||
}
|
||||
|
||||
public static Gradation FromOe(double oe) {
|
||||
return new Gradation(0); // TODO
|
||||
}
|
||||
|
||||
public static Gradation FromOe(double oe, double t) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
45
Elwig/Helpers/TempFile.cs
Normal file
45
Elwig/Helpers/TempFile.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Elwig.Helpers {
|
||||
public sealed class TempFile : IDisposable {
|
||||
private int Usages = 0;
|
||||
public string FilePath { get; private set; }
|
||||
|
||||
public TempFile() : this(null) { }
|
||||
|
||||
public TempFile(string? ext) : this(Path.Combine(Path.GetTempPath(), "Elwig"), ext) { }
|
||||
|
||||
public TempFile(string dir, string? ext) {
|
||||
FilePath = Path.Combine(dir, Path.GetRandomFileName().Replace(".", "") + (ext != null ? $".{ext}" : ""));
|
||||
Usages++;
|
||||
Create();
|
||||
}
|
||||
|
||||
~TempFile() {
|
||||
Delete();
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
if (--Usages == 0) {
|
||||
Delete();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
public TempFile NewReference() {
|
||||
Usages++;
|
||||
return this;
|
||||
}
|
||||
|
||||
private void Create() {
|
||||
using (File.Create(FilePath)) { };
|
||||
}
|
||||
|
||||
private void Delete() {
|
||||
if (FilePath == null) return;
|
||||
File.Delete(FilePath);
|
||||
FilePath = null;
|
||||
}
|
||||
}
|
||||
}
|
99
Elwig/Helpers/Utils.cs
Normal file
99
Elwig/Helpers/Utils.cs
Normal file
@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Controls.Primitives;
|
||||
|
||||
namespace Elwig.Helpers {
|
||||
public static class Utils {
|
||||
public static void SetInputChanged(Control input) {
|
||||
var brush = Brushes.Orange;
|
||||
if (input is ComboBox cb) {
|
||||
var border = GetComboBoxBorder(cb);
|
||||
if (border != null)
|
||||
border.BorderBrush = brush;
|
||||
} else {
|
||||
input.BorderBrush = brush;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetInputInvalid(Control input) {
|
||||
var brush = Brushes.Red;
|
||||
if (input is ComboBox cb) {
|
||||
var border = GetComboBoxBorder(cb);
|
||||
if (border != null)
|
||||
border.BorderBrush = brush;
|
||||
} else {
|
||||
input.BorderBrush = brush;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ClearInputState(Control input) {
|
||||
if (input is ComboBox cb) {
|
||||
GetComboBoxBorder(cb)?.ClearValue(Border.BorderBrushProperty);
|
||||
} else {
|
||||
input.ClearValue(Control.BorderBrushProperty);
|
||||
}
|
||||
}
|
||||
|
||||
private static Border? GetComboBoxBorder(ComboBox cb) {
|
||||
var toggleButton = cb.Template.FindName("toggleButton", cb) as ToggleButton;
|
||||
return toggleButton?.Template.FindName("templateRoot", toggleButton) as Border;
|
||||
}
|
||||
|
||||
public static IEnumerable<T> FindVisualChilds<T>(DependencyObject depObj) where T : DependencyObject {
|
||||
if (depObj == null)
|
||||
yield return (T)Enumerable.Empty<T>();
|
||||
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) {
|
||||
DependencyObject ithChild = VisualTreeHelper.GetChild(depObj, i);
|
||||
if (ithChild == null)
|
||||
continue;
|
||||
if (ithChild is T t)
|
||||
yield return t;
|
||||
foreach (T childOfChild in FindVisualChilds<T>(ithChild))
|
||||
yield return childOfChild;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<T> FindVisualChilds<T>(DependencyObject depObj, IEnumerable<DependencyObject> exempt) where T : DependencyObject {
|
||||
return FindVisualChilds<T>(depObj).Where(c => !exempt.Contains(c));
|
||||
}
|
||||
|
||||
public static int Modulo(string a, int b) {
|
||||
if (!a.All(char.IsDigit))
|
||||
throw new ArgumentException("First argument has to be a decimal string");
|
||||
return a.Select(ch => ch - '0').Aggregate((sum, n) => (sum * 10 + n) % b);
|
||||
}
|
||||
|
||||
public static void RunBackground(string title, Func<Task> a) {
|
||||
Task.Run(async () => {
|
||||
try {
|
||||
await a();
|
||||
} catch (Exception e) {
|
||||
MessageBox.Show(e.ToString(), title, MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void MailTo(string emailAddress) {
|
||||
Process.Start(new ProcessStartInfo() {
|
||||
FileName = $"mailto:{emailAddress}",
|
||||
UseShellExecute = true,
|
||||
});
|
||||
}
|
||||
|
||||
public static bool MgNrExists(AppDbContext ctx, int mgnr) {
|
||||
return ctx.Members.Find(mgnr) != null;
|
||||
}
|
||||
|
||||
public static int NextMgNr(AppDbContext ctx) {
|
||||
int c = ctx.Members.Select(m => m.MgNr).Min();
|
||||
ctx.Members.OrderBy(m => m.MgNr).Select(m => m.MgNr).ToList().ForEach(a => { if (a <= c + 100) c = a; });
|
||||
return c + 1;
|
||||
}
|
||||
}
|
||||
}
|
300
Elwig/Helpers/Validator.cs
Normal file
300
Elwig/Helpers/Validator.cs
Normal file
@ -0,0 +1,300 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Controls;
|
||||
using Elwig.Models;
|
||||
|
||||
namespace Elwig.Helpers {
|
||||
static class Validator {
|
||||
|
||||
private static readonly Dictionary<string, string[][]> PHONE_NRS = new() {
|
||||
{ "43", new string[][] {
|
||||
Array.Empty<string>(),
|
||||
new string[] { "57", "59" },
|
||||
new string[] {
|
||||
"50", "517", "718", "804", "720", "780", "800", "802", "810",
|
||||
"820", "821", "828", "900", "901", "930", "931", "939",
|
||||
"650", "651", "652", "653", "655", "657", "659", "660", "661",
|
||||
"663", "664", "665", "666", "667", "668", "669", "67", "68", "69"
|
||||
}
|
||||
} },
|
||||
{ "49", Array.Empty<string[]>() },
|
||||
{ "48", Array.Empty<string[]>() },
|
||||
{ "420", Array.Empty<string[]>() },
|
||||
{ "421", Array.Empty<string[]>() },
|
||||
{ "36", Array.Empty<string[]>() },
|
||||
{ "386", Array.Empty<string[]>() },
|
||||
{ "39", Array.Empty<string[]>() },
|
||||
{ "33", Array.Empty<string[]>() },
|
||||
{ "41", Array.Empty<string[]>() },
|
||||
{ "423", Array.Empty<string[]>() },
|
||||
};
|
||||
|
||||
public static ValidationResult CheckNumeric(TextBox input, bool optional) {
|
||||
return CheckNumeric(input, optional, -1);
|
||||
}
|
||||
|
||||
private static ValidationResult CheckNumeric(TextBox input, bool optional, int maxLen) {
|
||||
string text = "";
|
||||
int pos = input.CaretIndex;
|
||||
for (int i = 0; i < input.Text.Length; i++) {
|
||||
char ch = input.Text[i];
|
||||
if (char.IsDigit(ch))
|
||||
text += ch;
|
||||
if (i == input.CaretIndex - 1)
|
||||
pos = text.Length;
|
||||
}
|
||||
input.Text = text;
|
||||
input.CaretIndex = pos;
|
||||
|
||||
if (text.Length == 0) {
|
||||
if (optional) return new(true, null);
|
||||
return new(false, "Wert ist nicht optional");
|
||||
}
|
||||
|
||||
if (maxLen >= 0 && input.Text.Length > maxLen) {
|
||||
input.Text = input.Text[..maxLen];
|
||||
input.CaretIndex = Math.Min(pos, maxLen);
|
||||
}
|
||||
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckPlz(TextBox input, bool optional, AppDbContext ctx) {
|
||||
CheckNumeric(input, true, 4);
|
||||
if (optional && input.Text.Length == 0) {
|
||||
return new(true, null);
|
||||
} else if (input.Text.Length != 4) {
|
||||
return new(false, "PLZ zu kurz");
|
||||
}
|
||||
int plz = int.Parse(input.Text);
|
||||
if (!ctx.Postleitzahlen.Any(p => p.Plz == plz)) {
|
||||
return new(false, "Ungültige PLZ");
|
||||
}
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckPhoneNumber(TextBox input, bool optional) {
|
||||
string text = "";
|
||||
int pos = input.CaretIndex;
|
||||
for (int i = 0, v = 0; i < input.Text.Length && v < 30; i++) {
|
||||
char ch = input.Text[i];
|
||||
if (v == 0 && input.Text.Length - i >= 2 && ch == '0' && input.Text[i + 1] == '0') {
|
||||
v++; i++;
|
||||
text += '+';
|
||||
} else if (ch == '(' && input.Text.Length - i >= 3 && input.Text[i + 1] == '0' && input.Text[i + 2] == ')') {
|
||||
i += 2;
|
||||
} else if (v == 0 && ch == '0') {
|
||||
v += 3;
|
||||
text += "+43";
|
||||
} else if (v == 0 && ch == '+') {
|
||||
v++;
|
||||
text += ch;
|
||||
} else if (v > 0 && char.IsDigit(ch)) {
|
||||
if (PHONE_NRS.Any(kv => text == "+" + kv.Key))
|
||||
text += ' ';
|
||||
if (text.StartsWith("+43 ")) {
|
||||
var nr = text[4..];
|
||||
var vws = PHONE_NRS["43"];
|
||||
if (v >= 4 && v - 4 < vws.Length && vws[v - 4].Any(vw => nr.StartsWith(vw)))
|
||||
text += ' ';
|
||||
else if (nr == "1")
|
||||
text += ' ';
|
||||
else if (v == 7 && nr.Length == 4)
|
||||
text += ' ';
|
||||
}
|
||||
v++;
|
||||
text += ch;
|
||||
}
|
||||
if (i == input.CaretIndex - 1)
|
||||
pos = text.Length;
|
||||
}
|
||||
input.Text = text;
|
||||
input.CaretIndex = pos;
|
||||
|
||||
if (optional && text.Length == 0)
|
||||
return new(true, null);
|
||||
if (text.Length < 10)
|
||||
return new(false, "Telefonnummer zu kurz");
|
||||
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckEmailAddress(TextBox input, bool optional) {
|
||||
string text = "";
|
||||
int pos = input.CaretIndex;
|
||||
bool domain = false;
|
||||
for (int i = 0; i < input.Text.Length && text.Length < 256; i++) {
|
||||
char ch = input.Text[i];
|
||||
if (domain) {
|
||||
if ((char.IsAscii(ch) && char.IsLetterOrDigit(ch)) || ".-_öäüßÖÄÜẞ".Any(c => c == ch)) {
|
||||
if (!(text.Last() == '.' && ch == '.'))
|
||||
text += char.ToLower(ch);
|
||||
}
|
||||
} else {
|
||||
if (ch == '@')
|
||||
domain = true;
|
||||
if (!char.IsControl(ch) && !char.IsWhiteSpace(ch))
|
||||
text += ch;
|
||||
}
|
||||
|
||||
if (i == input.CaretIndex - 1)
|
||||
pos = text.Length;
|
||||
}
|
||||
input.Text = text;
|
||||
input.CaretIndex = pos;
|
||||
|
||||
if (text.Length == 0) {
|
||||
if (optional) return new(true, null);
|
||||
return new(false, "E-Mail-Adresse ist nicht optional");
|
||||
} else if (text[0] == '@' || !domain) {
|
||||
return new(false, "E-Mail-Adresse ungültig");
|
||||
}
|
||||
|
||||
var last = text.Split(".").Last();
|
||||
if (last.Length < 2 || !last.All(ch => char.IsAscii(ch) && char.IsLower(ch)))
|
||||
return new(false, "E-Mail-Adresse ungültig");
|
||||
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckIban(TextBox input, bool optional) {
|
||||
string text = "";
|
||||
int pos = input.CaretIndex;
|
||||
int v = 0;
|
||||
for (int i = 0; i < input.Text.Length && v < 34; i++) {
|
||||
char ch = input.Text[i];
|
||||
if (char.IsLetterOrDigit(ch) && char.IsAscii(ch)) {
|
||||
if (((v < 2 && char.IsLetter(ch)) || (v >= 2 && v < 4 && char.IsDigit(ch)) || v >= 4) &&
|
||||
((!text.StartsWith("AT") && !text.StartsWith("DE")) || char.IsDigit(ch)))
|
||||
{
|
||||
if (v != 0 && v % 4 == 0)
|
||||
text += ' ';
|
||||
v++;
|
||||
text += char.ToUpper(ch);
|
||||
}
|
||||
}
|
||||
if (i == input.CaretIndex - 1)
|
||||
pos = text.Length;
|
||||
if (text.StartsWith("AT") && v >= 20)
|
||||
break;
|
||||
else if (text.StartsWith("DE") && v >= 22)
|
||||
break;
|
||||
}
|
||||
input.Text = text;
|
||||
input.CaretIndex = pos;
|
||||
|
||||
if (optional && text.Length == 0) {
|
||||
return new(true, null);
|
||||
} else if (v < 5 || (text.StartsWith("AT") && v != 20) || (text.StartsWith("DE") && v != 22)) {
|
||||
return new(false, "IBAN hat falsche Länge");
|
||||
}
|
||||
|
||||
var validation = (text[4..] + text[..4]).Replace(" ", "")
|
||||
.Select(ch => char.IsDigit(ch) ? ch.ToString() : (ch - 'A' + 10).ToString())
|
||||
.Aggregate((a, b) => a + b);
|
||||
if (Utils.Modulo(validation, 97) != 1)
|
||||
return new(false, "Prüfsumme der IBAN ist falsch");
|
||||
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckBic(TextBox input, bool optional) {
|
||||
string text = "";
|
||||
int pos = input.CaretIndex;
|
||||
for (int i = 0, v = 0; i < input.Text.Length; i++) {
|
||||
char ch = input.Text[i];
|
||||
if ((v < 4 || v >= 6) && char.IsAscii(ch) && char.IsLetterOrDigit(ch)) {
|
||||
v++;
|
||||
text += char.ToUpper(ch);
|
||||
} else if (v >= 4 && v < 6 && char.IsAscii(ch) && char.IsLetter(ch)) {
|
||||
v++;
|
||||
text += char.ToUpper(ch);
|
||||
}
|
||||
|
||||
if (i == input.CaretIndex - 1)
|
||||
pos = text.Length;
|
||||
}
|
||||
|
||||
if (text.Length == 0) {
|
||||
if (optional) return new(true, null);
|
||||
return new(false, "BIC ist nicht optional");
|
||||
}
|
||||
|
||||
if (text.Length > 11) {
|
||||
text = text[..11];
|
||||
pos = Math.Min(pos, 11);
|
||||
}
|
||||
|
||||
if (text.Length == 11 && text.EndsWith("XXX"))
|
||||
text = text[..8];
|
||||
|
||||
input.Text = text;
|
||||
input.CaretIndex = pos;
|
||||
|
||||
if (text.Length != 11 && text.Length != 8)
|
||||
return new(false, "BIC ist ungültig");
|
||||
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckLfbisNr(TextBox input, bool optional) {
|
||||
var res = CheckNumeric(input, true, 7);
|
||||
if (!res.IsValid) {
|
||||
return res;
|
||||
} else if (optional && input.Text.Length == 0) {
|
||||
return new(true, null);
|
||||
} else if (input.Text.Length != 7) {
|
||||
return new(false, "Betriebsnummer zu kurz");
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
||||
return new(true, "Not implemented yet");
|
||||
}
|
||||
|
||||
public static ValidationResult CheckUstId(TextBox input, bool optional) {
|
||||
// TODO
|
||||
return new(true, "Not implemented yet");
|
||||
}
|
||||
|
||||
public static ValidationResult CheckMgNr(TextBox input, bool optional, AppDbContext ctx, Member? m) {
|
||||
var res = CheckNumeric(input, optional);
|
||||
if (!res.IsValid) {
|
||||
return res;
|
||||
} else if (optional && input.Text.Length == 0) {
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
int nr = int.Parse(input.Text);
|
||||
if (nr != m?.MgNr && Utils.MgNrExists(ctx, nr)) {
|
||||
return new(false, "Mitgliedsnummer wird bereits verwendet");
|
||||
}
|
||||
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckPredecessorMgNr(TextBox input, bool optional, AppDbContext ctx) {
|
||||
var res = CheckNumeric(input, optional);
|
||||
if (!res.IsValid) {
|
||||
return res;
|
||||
} else if (optional && input.Text.Length == 0) {
|
||||
return new(true, null);
|
||||
} else if (!Utils.MgNrExists(ctx, int.Parse(input.Text))) {
|
||||
return new(false, "Ein Mitglied mit dieser Mitgliedsnummer existiert nicht");
|
||||
}
|
||||
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckDate(TextBox input, bool optional) {
|
||||
// TODO
|
||||
return new(true, "Not implemented yet");
|
||||
}
|
||||
|
||||
public static ValidationResult CheckPartialDate(TextBox input, bool optional) {
|
||||
// TODO
|
||||
return new(true, "Not implemented yet");
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user