329 lines
14 KiB
C#
329 lines
14 KiB
C#
using System;
|
|
using System.Data;
|
|
using System.Linq;
|
|
using System.Windows;
|
|
using System.IO;
|
|
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;
|
|
using Elwig.Dialogs;
|
|
using System.Threading.Tasks;
|
|
using Elwig.Helpers.Billing;
|
|
using Elwig.Models.Entities;
|
|
using System.Text;
|
|
|
|
namespace Elwig {
|
|
public partial class App : Application {
|
|
|
|
protected static App CurrentApp;
|
|
public static int NumWindows => CurrentApp.Windows.Count;
|
|
public static bool ForceShutdown { get; private set; } = false;
|
|
|
|
private readonly DispatcherTimer _autoUpdateTimer = new() { Interval = TimeSpan.FromHours(1) };
|
|
|
|
public static readonly string DataPath = @"C:\ProgramData\Elwig\";
|
|
public static readonly string ConfigPath = Path.Combine(DataPath, "config.ini");
|
|
public static readonly string ExePath = @"C:\Program Files\Elwig\";
|
|
public static readonly string TempPath = Path.Combine(Path.GetTempPath(), "Elwig");
|
|
|
|
public static Config Config { get; private set; } = new(ConfigPath);
|
|
public static Version Version { get; private set; } = new();
|
|
|
|
public static int BranchNum { get; private set; }
|
|
public static string ZwstId { get; private set; }
|
|
public static string BranchName { get; private set; }
|
|
public static int? BranchPlz { get; private set; }
|
|
public static string? BranchLocation { get; private set; }
|
|
public static string? BranchAddress { get; private set; }
|
|
public static string? BranchPhoneNr { get; private set; }
|
|
public static string? BranchFaxNr { get; private set; }
|
|
public static string? BranchMobileNr { get; private set; }
|
|
public static IList<IScale> Scales { get; private set; }
|
|
public static IList<ICommandScale> CommandScales => Scales.Where(s => s is ICommandScale).Cast<ICommandScale>().ToList();
|
|
public static IList<IEventScale> EventScales => Scales.Where(s => s is IEventScale).Cast<IEventScale>().ToList();
|
|
public static ClientParameters Client { get; set; }
|
|
|
|
public static Dispatcher MainDispatcher { get; private set; }
|
|
private DateTime LastChanged;
|
|
private static DateTime CurrentLastWrite => File.GetLastWriteTime(Config.DatabaseFile);
|
|
private readonly DispatcherTimer ContextTimer = new() { Interval = TimeSpan.FromSeconds(2) };
|
|
|
|
public App() : base() {
|
|
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
|
Directory.CreateDirectory(TempPath);
|
|
Directory.CreateDirectory(DataPath);
|
|
MainDispatcher = Dispatcher;
|
|
Scales = [];
|
|
CurrentApp = this;
|
|
OverrideCulture();
|
|
|
|
var args = Environment.GetCommandLineArgs();
|
|
if (args.Length >= 2) {
|
|
Config = new(Path.GetFullPath(args[1]));
|
|
}
|
|
|
|
ContextTimer.Tick += (object? sender, EventArgs evt) => {
|
|
var ch = CurrentLastWrite;
|
|
if (ch > LastChanged) {
|
|
LastChanged = ch;
|
|
OnContextChanged();
|
|
}
|
|
};
|
|
}
|
|
|
|
private static void OnContextChanged() {
|
|
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");
|
|
|
|
try {
|
|
await AppDbUpdater.CheckDb();
|
|
} catch (Exception e) {
|
|
if (Config.UpdateUrl != null && Utils.HasInternetConnectivity()) {
|
|
await CheckForUpdates();
|
|
}
|
|
MessageBox.Show($"Invalid Database:\n\n{e.Message}", "Invalid Database", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
Shutdown();
|
|
return;
|
|
}
|
|
|
|
LastChanged = CurrentLastWrite;
|
|
ContextTimer.Start();
|
|
|
|
Dictionary<string, (string, string, int?, string?, string?, string?, string?, string?)> branches = [];
|
|
using (var ctx = new AppDbContext()) {
|
|
branches = ctx.Branches.ToDictionary(b => b.Name.ToLower(), b => (b.ZwstId, b.Name, b.PostalDest?.AtPlz?.Plz, b.PostalDest?.AtPlz?.Ort.Name, b.Address, b.PhoneNr, b.FaxNr, b.MobileNr));
|
|
try {
|
|
Client = new(ctx);
|
|
} catch (Exception e) {
|
|
MessageBox.Show($"Fehler beim Laden der Mandantendaten:\n\n{e.Message}", "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
Shutdown();
|
|
return;
|
|
}
|
|
BranchNum = branches.Count;
|
|
}
|
|
|
|
Utils.RunBackground("Temp File Cleanup", () => {
|
|
Utils.CleanupTempFiles();
|
|
return Task.CompletedTask;
|
|
});
|
|
|
|
Utils.RunBackground("HTML Initialization", () => Html.Init());
|
|
Utils.RunBackground("PDF Initialization", () => Pdf.Init());
|
|
Utils.RunBackground("JSON Schema Initialization", BillingData.Init);
|
|
|
|
if (Config.UpdateAuto && Config.UpdateUrl != null) {
|
|
if (Utils.HasInternetConnectivity()) {
|
|
Utils.RunBackground("Auto Updater", async () => {
|
|
await Task.Delay(500);
|
|
await CheckForUpdates();
|
|
});
|
|
}
|
|
_autoUpdateTimer.Tick += new EventHandler(OnAutoUpdateTimer);
|
|
_autoUpdateTimer.Start();
|
|
}
|
|
|
|
var list = new List<IScale>();
|
|
foreach (var s in Config.Scales) {
|
|
try {
|
|
list.Add(Scale.FromConfig(s));
|
|
} catch (Exception e) {
|
|
list.Add(new InvalidScale(s.Id));
|
|
if (s.Required)
|
|
MessageBox.Show($"Unable to create scale {s.Id}:\n\n{e.Message}", "Scale Error",
|
|
MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
}
|
|
Scales = list;
|
|
|
|
if (Config.Branch != null) {
|
|
if (!branches.ContainsKey(Config.Branch.ToLower())) {
|
|
MessageBox.Show("Invalid branch name in config!", "Invalid Branch Config", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
Shutdown();
|
|
} else {
|
|
SetBranch(branches[Config.Branch.ToLower()]);
|
|
}
|
|
} else if (branches.Count == 1) {
|
|
SetBranch(branches.First().Value);
|
|
} else {
|
|
MessageBox.Show("Unable to determine local branch!", "Invalid Branch Config", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
Shutdown();
|
|
}
|
|
|
|
base.OnStartup(evt);
|
|
|
|
var window = new MainWindow();
|
|
window.Show();
|
|
}
|
|
|
|
private async void Application_Exit(object sender, ExitEventArgs evt) {
|
|
await Pdf.Cleanup();
|
|
}
|
|
|
|
public static void SetBranch(Branch b) {
|
|
SetBranch((b.ZwstId, b.Name, b.PostalDest?.AtPlz?.Plz, b.PostalDest?.AtPlz?.Ort.Name, b.Address, b.PhoneNr, b.FaxNr, b.MobileNr));
|
|
}
|
|
|
|
private static void SetBranch((string, string, int?, string?, string?, string?, string?, string?) entry) {
|
|
ZwstId = entry.Item1;
|
|
BranchName = entry.Item2;
|
|
BranchPlz = entry.Item3;
|
|
BranchLocation = entry.Item4?.Split(" im ")[0].Split(" an ")[0].Split(" bei ")[0]; // FIXME
|
|
BranchAddress = entry.Item5;
|
|
BranchPhoneNr = entry.Item6;
|
|
BranchFaxNr = entry.Item7;
|
|
BranchMobileNr = entry.Item8;
|
|
}
|
|
|
|
public static void HintContextChange() {
|
|
var ch = CurrentLastWrite;
|
|
if (ch > CurrentApp.LastChanged)
|
|
CurrentApp.LastChanged = ch;
|
|
foreach (Window w in CurrentApp.Windows) {
|
|
if (w is not ContextWindow c) continue;
|
|
MainDispatcher.BeginInvoke(c.HintContextChange);
|
|
}
|
|
}
|
|
|
|
private void OnAutoUpdateTimer(object? sender, EventArgs? evt) {
|
|
foreach (Window w in CurrentApp.Windows) {
|
|
if (w is UpdateDialog) return;
|
|
}
|
|
if (Utils.HasInternetConnectivity()) {
|
|
Utils.RunBackground("Auto Updater", async () => await CheckForUpdates());
|
|
}
|
|
}
|
|
|
|
public static async Task CheckForUpdates(bool showAlert = false) {
|
|
if (Config.UpdateUrl == null) return;
|
|
var latest = await Utils.GetLatestInstallerUrl(Config.UpdateUrl);
|
|
if (latest != null && new Version(latest.Value.Version) > Version) {
|
|
await MainDispatcher.BeginInvoke(() => {
|
|
var d = new UpdateDialog(latest.Value.Version, latest.Value.Url, latest.Value.Size);
|
|
if (d.ShowDialog() == true) {
|
|
ForceShutdown = true;
|
|
Current.Shutdown();
|
|
}
|
|
});
|
|
} else if (showAlert) {
|
|
if (latest == null) {
|
|
MessageBox.Show("Informationen konnten nicht abgerufen werden!", "Nach Updates suchen",
|
|
MessageBoxButton.OK, MessageBoxImage.Error);
|
|
} else {
|
|
MessageBox.Show($"Elwig ist auf dem aktuellsten Stand! (Version: {latest.Value.Version})", "Nach Updates suchen",
|
|
MessageBoxButton.OK, MessageBoxImage.Information);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static T FocusWindow<T>(Func<T> constructor, Predicate<T>? selector = null) where T : Window {
|
|
foreach (Window w in CurrentApp.Windows) {
|
|
if (w is T t && (selector == null || selector(t))) {
|
|
if (t.WindowState == WindowState.Minimized)
|
|
t.WindowState = WindowState.Normal;
|
|
t.Activate();
|
|
return t;
|
|
}
|
|
}
|
|
var n = constructor();
|
|
n.Show();
|
|
return n;
|
|
}
|
|
|
|
public static DeliveryAdminWindow FocusReceipt() {
|
|
return FocusWindow<DeliveryAdminWindow>(() => new(true), w => w.ViewModel.IsReceipt);
|
|
}
|
|
|
|
public static DeliveryAdminWindow FocusMemberDeliveries(int mgnr) {
|
|
return FocusWindow<DeliveryAdminWindow>(() => new(mgnr), w => w.ViewModel.FilterMember?.MgNr == mgnr);
|
|
}
|
|
|
|
public static AreaComAdminWindow FocusMemberAreaComs(int mgnr) {
|
|
return FocusWindow<AreaComAdminWindow>(() => new(mgnr), w => w.ViewModel.FilterMember.MgNr == mgnr);
|
|
}
|
|
|
|
public static BaseDataWindow FocusBaseData() {
|
|
return FocusWindow<BaseDataWindow>(() => new());
|
|
}
|
|
|
|
public static BaseDataWindow FocusBaseDataAreaComType() {
|
|
var w = FocusBaseData();
|
|
w.AreaCommitmentTypes.Focus();
|
|
return w;
|
|
}
|
|
|
|
public static BaseDataWindow FocusBaseDataSeason(int year) {
|
|
var w = FocusBaseData();
|
|
w.Seasons.Focus();
|
|
ControlUtils.SelectItemWithPk(w.SeasonList, year);
|
|
return w;
|
|
}
|
|
|
|
public static OriginHierarchyWindow FocusOriginHierarchy() {
|
|
return FocusWindow<OriginHierarchyWindow>(() => new());
|
|
}
|
|
|
|
public static OriginHierarchyWindow FocusOriginHierarchyKg(int kgnr) {
|
|
var w = FocusOriginHierarchy();
|
|
w.FocusKgNr(kgnr);
|
|
return w;
|
|
}
|
|
|
|
public static DeliveryAncmtAdminWindow FocusDeliveryAncmt() {
|
|
return FocusWindow<DeliveryAncmtAdminWindow>(() => new());
|
|
}
|
|
|
|
public static DeliveryScheduleAdminWindow FocusDeliverySchedule() {
|
|
return FocusWindow<DeliveryScheduleAdminWindow>(() => new());
|
|
}
|
|
|
|
public static PaymentVariantsWindow FocusPaymentVariants(int year) {
|
|
return FocusWindow<PaymentVariantsWindow>(() => new(year), w => w.Year == year);
|
|
}
|
|
|
|
public static PaymentAdjustmentWindow FocusPaymentAdjustment(int year) {
|
|
return FocusWindow<PaymentAdjustmentWindow>(() => new(year), w => w.Year == year);
|
|
}
|
|
|
|
public static ChartWindow FocusChartWindow(int year, int avnr) {
|
|
return FocusWindow<ChartWindow>(() => new(year, avnr), w => w.Year == year && w.AvNr == avnr);
|
|
}
|
|
|
|
public static MemberAdminWindow FocusMember(int mgnr) {
|
|
var w = FocusWindow<MemberAdminWindow>(() => new());
|
|
w.FocusMember(mgnr);
|
|
return w;
|
|
}
|
|
|
|
public static MailWindow FocusMailWindow(int? year = null) {
|
|
return FocusWindow<MailWindow>(() => new(year), w => year == null || w.Year == year);
|
|
}
|
|
}
|
|
}
|