using System.IO.Compression; using System.IO; using System.Threading.Tasks; using Elwig.Models.Entities; using System.Collections.Generic; using System; using System.Text.Json.Nodes; using System.Linq; using System.Windows; using Microsoft.EntityFrameworkCore; namespace Elwig.Helpers.Export { public static class ElwigData { public static readonly string ImportedTxt = Path.Combine(App.DataPath, "imported.txt"); public static async Task GetImportedFiles() { try { return await File.ReadAllLinesAsync(ImportedTxt, Utils.UTF8); } catch { return []; } } public static async Task AddImportedFiles(IEnumerable filenames) { await File.AppendAllLinesAsync(ImportedTxt, filenames, Utils.UTF8); } public static Task Import(string filename, bool interactive) => Import([filename], interactive); public static async Task Import(IEnumerable filenames, bool interactive) { try { using var ctx = new AppDbContext(); var currentDids = await ctx.Deliveries .GroupBy(d => d.Year) .ToDictionaryAsync(g => g.Key, g => g.Max(d => d.DId)); var deliveries = new List(); var deliveryParts = new List(); var modifiers = new List(); var metaData = new List<(string Name, int DeliveryNum, string Filters)>(); foreach (var filename in filenames) { using var zip = ZipFile.Open(filename, ZipArchiveMode.Read); var version = zip.GetEntry("version"); using (var reader = new StreamReader(version!.Open(), Utils.UTF8)) { if (await reader.ReadToEndAsync() != "elwig:1") throw new FileFormatException("Ungültige Export-Datei"); } var metaJson = zip.GetEntry("meta.json"); var meta = await JsonNode.ParseAsync(metaJson!.Open()); var deliveryCount = meta!["deliveries"]?["count"]!.AsValue().GetValue(); var deliveryFilters = meta!["deliveries"]?["filters"]!.AsArray().Select(f => f!.AsValue().GetValue()).ToArray(); if (deliveryCount != null && deliveryFilters != null) metaData.Add((Path.GetFileName(filename), (int)deliveryCount, string.Join(" / ", deliveryFilters))); var membersJson = zip.GetEntry("members.json"); if (membersJson != null) { using var reader = new StreamReader(membersJson.Open(), Utils.UTF8); string? line; while ((line = await reader.ReadLineAsync()) != null) { var obj = JsonNode.Parse(line)!.AsObject(); // TODO import members.json } } var areaComsJson = zip.GetEntry("area_commitments.json"); if (areaComsJson != null) { using var reader = new StreamReader(areaComsJson.Open(), Utils.UTF8); string? line; while ((line = await reader.ReadLineAsync()) != null) { var obj = JsonNode.Parse(line)!.AsObject(); // TODO import area_commitments.json } } var deliveriesJson = zip.GetEntry("deliveries.json"); if (deliveriesJson != null) { using var reader = new StreamReader(deliveriesJson.Open(), Utils.UTF8); string? line; while ((line = await reader.ReadLineAsync()) != null) { var obj = JsonNode.Parse(line)!.AsObject(); var (d, parts, mods) = JsonToDelivery(obj, currentDids); deliveries.Add(d); deliveryParts.AddRange(parts); modifiers.AddRange(mods); } } } var lsnrs = deliveries.Select(d => d.LsNr).ToList(); var duplicateLsNrs = await ctx.Deliveries .Where(d => lsnrs.Contains(d.LsNr)) .Select(d => d.LsNr) .ToListAsync(); var duplicateDIds = deliveries .Where(d => duplicateLsNrs.Contains(d.LsNr)) .Select(d => (d.Year, d.DId)) .ToList(); bool overwriteDelivieries = false; if (duplicateLsNrs.Count > 0) { var res = MessageBox.Show($"Sollen {duplicateLsNrs.Count} Lieferungen überschreiben werden?", "Lieferungen überschreiben", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No); overwriteDelivieries = res == MessageBoxResult.Yes; } if (overwriteDelivieries) { ctx.RemoveRange(ctx.Deliveries.Where(d => duplicateLsNrs.Contains(d.LsNr))); ctx.AddRange(deliveries); ctx.AddRange(deliveryParts); ctx.AddRange(modifiers); } else { ctx.AddRange(deliveries.Where(d => !duplicateDIds.Contains((d.Year, d.DId)))); ctx.AddRange(deliveryParts.Where(p => !duplicateDIds.Contains((p.Year, p.DId)))); ctx.AddRange(modifiers.Where(m => !duplicateDIds.Contains((m.Year, m.DId)))); } await ctx.SaveChangesAsync(); await AddImportedFiles(filenames.Select(f => Path.GetFileName(f))); await App.HintContextChange(); MessageBox.Show( $"Das importieren der Daten war erfolgreich!\n" + $"Folgendes wurde importiert:\n" + $" Lieferungen: {deliveries.Count}\n" + string.Join("\n", metaData.Select(d => $" {d.Name} ({d.DeliveryNum})\n {d.Filters}")) + "\n", "Importieren erfolgreich", MessageBoxButton.OK, MessageBoxImage.Information); } catch (Exception exc) { MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); } } public static async Task ExportDeliveries(string filename, IEnumerable deliveries, IEnumerable filters) { File.Delete(filename); using var zip = ZipFile.Open(filename, ZipArchiveMode.Create); var version = zip.CreateEntry("version", CompressionLevel.NoCompression); using (var writer = new StreamWriter(version.Open(), Utils.UTF8)) { await writer.WriteAsync("elwig:1"); } var meta = zip.CreateEntry("meta.json", CompressionLevel.NoCompression); using (var writer = new StreamWriter(meta.Open(), Utils.UTF8)) { await writer.WriteAsync( $"{{\"timestamp\": \"{DateTime.UtcNow:yyyy-MM-ddTHH:mm:ssZ}\", " + $"\"zwstid\": \"{App.ZwstId}\", \"device\": \"{Environment.MachineName}\", " + $"\"deliveries\": {{" + $"\"count\": {deliveries.Count()}, " + $"\"parts\": {deliveries.Sum(d => d.Parts.Count)}, " + $"\"filters\": [{string.Join(", ", filters.Select(f => '"' + f + '"'))}]" + $"}}}}"); } var json = zip.CreateEntry("deliveries.json"); using (var writer = new StreamWriter(json.Open(), Utils.UTF8)) { foreach (var d in deliveries) { await writer.WriteLineAsync(DeliveryToJson(d).ToJsonString()); } } } public static JsonObject DeliveryToJson(Delivery d) { return new JsonObject { ["lsnr"] = d.LsNr, ["year"] = d.Year, ["date"] = $"{d.Date:yyyy-MM-dd}", ["zwstid"] = d.ZwstId, ["lnr"] = d.LNr, ["time"] = d.Time != null ? $"{d.Time:HH:mm:ss}" : null, ["mgnr"] = d.MgNr, ["parts"] = new JsonArray(d.Parts.OrderBy(p => p.DPNr).Select(p => { var obj = new JsonObject { ["dpnr"] = p.DPNr, ["sortid"] = p.SortId, ["attrid"] = p.AttrId, ["cultid"] = p.CultId, ["weight"] = p.Weight, ["kmw"] = p.Kmw, ["qualid"] = p.QualId, ["hkid"] = p.HkId, ["kgnr"] = p.KgNr, ["rdnr"] = p.RdNr, ["net_weight"] = p.IsNetWeight, ["manual_weighing"] = p.IsManualWeighing, ["modids"] = new JsonArray(p.Modifiers.Select(m => (JsonNode)m.ModId).ToArray()), ["comment"] = p.Comment, }; if (p.IsSplCheck) obj["spl_check"] = p.IsSplCheck; if (p.IsHandPicked != null) obj["hand_picked"] = p.IsHandPicked; if (p.IsLesewagen != null) obj["lesewagen"] = p.IsLesewagen; if (p.IsGebunden != null) obj["gebunden"] = p.IsGebunden; if (p.Temperature != null) obj["temperature"] = p.Temperature; if (p.Acid != null) obj["acid"] = p.Acid; if (p.ScaleId != null) obj["scale_id"] = p.ScaleId; if (p.WeighingId != null) obj["weighing_id"] = p.WeighingId; if (p.WeighingReason != null) obj["weighing_reason"] = p.WeighingReason; return obj; }).ToArray()), ["comment"] = d.Comment, }; } public static (Delivery, List, List) JsonToDelivery(JsonNode json, Dictionary currentDids) { var year = json["year"]!.AsValue().GetValue(); var did = ++currentDids[year]; return (new Delivery { Year = year, DId = did, DateString = json["date"]!.AsValue().GetValue(), TimeString = json["time"]?.AsValue().GetValue(), ZwstId = json["zwstid"]!.AsValue().GetValue(), LNr = json["lnr"]!.AsValue().GetValue(), LsNr = json["lsnr"]!.AsValue().GetValue(), MgNr = json["mgnr"]!.AsValue().GetValue(), Comment = json["comment"]?.AsValue().GetValue(), }, json["parts"]!.AsArray().Select(p => p!.AsObject()).Select(p => new DeliveryPart { Year = year, DId = did, DPNr = p["dpnr"]!.AsValue().GetValue(), SortId = p["sortid"]!.AsValue().GetValue(), AttrId = p["attrid"]?.AsValue().GetValue(), CultId = p["cultid"]?.AsValue().GetValue(), Weight = p["weight"]!.AsValue().GetValue(), Kmw = p["kmw"]!.AsValue().GetValue(), QualId = p["qualid"]!.AsValue().GetValue(), HkId = p["hkid"]!.AsValue().GetValue(), KgNr = p["kgnr"]?.AsValue().GetValue(), RdNr = p["rdnr"]?.AsValue().GetValue(), IsNetWeight = p["net_weight"]!.AsValue().GetValue(), IsManualWeighing = p["manual_weighing"]!.AsValue().GetValue(), Comment = p["comment"]?.AsValue().GetValue(), IsSplCheck = p["spl_check"]?.AsValue().GetValue() ?? false, IsHandPicked = p["hand_picked"]?.AsValue().GetValue(), IsLesewagen = p["lesewagen"]?.AsValue().GetValue(), IsGebunden = p["gebunden"]?.AsValue().GetValue(), Temperature = p["temperature"]?.AsValue().GetValue(), Acid = p["acid"]?.AsValue().GetValue(), ScaleId = p["scale_id"]?.AsValue().GetValue(), WeighingId = p["weighing_id"]?.AsValue().GetValue(), WeighingReason = p["weighing_reason"]?.AsValue().GetValue(), }).ToList(), json["parts"]!.AsArray().SelectMany(p => p!["modids"]!.AsArray().Select(m => new DeliveryPartModifier { Year = year, DId = did, DPNr = p["dpnr"]!.AsValue().GetValue(), ModId = m!.AsValue().GetValue(), })).ToList()); } } }