Rename solution directory to Elwig

This commit is contained in:
2023-03-18 11:04:22 +01:00
parent 649578e8bf
commit 769d80eb81
48 changed files with 7 additions and 11 deletions

View 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();
}
}
}

View 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
View 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
View 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
View 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");
}
}
}