From 9d02f18bacffbb032dbfcf97ef035d45ccf35d84 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Thu, 25 Sep 2025 11:40:23 +0200 Subject: [PATCH] ElwigData: Fail more gracefully when single files may not be processed --- Elwig/Helpers/Export/ElwigData.cs | 182 +++++++++++++++++------------- 1 file changed, 101 insertions(+), 81 deletions(-) diff --git a/Elwig/Helpers/Export/ElwigData.cs b/Elwig/Helpers/Export/ElwigData.cs index a081f4e..8471735 100644 --- a/Elwig/Helpers/Export/ElwigData.cs +++ b/Elwig/Helpers/Export/ElwigData.cs @@ -77,97 +77,117 @@ namespace Elwig.Helpers.Export { int? DeliveryNum, string? DeliveryFilters)>(); foreach (var filename in filenames) { - // TODO read encrypted files - using var zip = ZipFile.Open(filename, ZipArchiveMode.Read); - await zip.CheckIntegrity(); + try { + data.Add(new([], [], [], [], [], [], [], new([], [], [], [], new() { + ["member"] = [], + ["area_commitment"] = [], + ["delivery"] = [], + }))); + var r = data[^1]; - 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 ({filename})"); - } + // TODO read encrypted files + using var zip = ZipFile.Open(filename, ZipArchiveMode.Read); + await zip.CheckIntegrity(); - var metaJson = zip.GetEntry("meta.json"); - var meta = await JsonNode.ParseAsync(metaJson!.Open()); - var memberCount = meta!["members"]?["count"]?.AsValue().GetValue(); - var memberFilters = meta!["members"]?["filters"]?.AsArray().Select(f => f!.AsValue().GetValue()).ToArray(); - var areaComCount = meta!["area_commitments"]?["count"]?.AsValue().GetValue(); - var areaComFilters = meta!["area_commitments"]?["filters"]?.AsArray().Select(f => f!.AsValue().GetValue()).ToArray(); - var deliveryCount = meta!["deliveries"]?["count"]?.AsValue().GetValue(); - var deliveryFilters = meta!["deliveries"]?["filters"]?.AsArray().Select(f => f!.AsValue().GetValue()).ToArray(); - metaData.Add((Path.GetFileName(filename), - meta["zwstid"]!.AsValue().GetValue(), meta["device"]!.AsValue().GetValue(), - memberCount, memberFilters != null ? string.Join(" / ", memberFilters) : null, - areaComCount, areaComFilters != null ? string.Join(" / ", areaComFilters) : null, - deliveryCount, deliveryFilters != null ? string.Join(" / ", deliveryFilters) : null)); + 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 Elwig-Export-Datei ({filename})"); + } - data.Add(new([], [], [], [], [], [], [], new([], [], [], [], new() { - ["member"] = [], - ["area_commitment"] = [], - ["delivery"] = [], - }))); - var r = data[^1]; + var metaJson = zip.GetEntry("meta.json"); + var meta = await JsonNode.ParseAsync(metaJson!.Open()); + var memberCount = meta!["members"]?["count"]?.AsValue().GetValue(); + var memberFilters = meta!["members"]?["filters"]?.AsArray().Select(f => f!.AsValue().GetValue()).ToArray(); + var areaComCount = meta!["area_commitments"]?["count"]?.AsValue().GetValue(); + var areaComFilters = meta!["area_commitments"]?["filters"]?.AsArray().Select(f => f!.AsValue().GetValue()).ToArray(); + var deliveryCount = meta!["deliveries"]?["count"]?.AsValue().GetValue(); + var deliveryFilters = meta!["deliveries"]?["filters"]?.AsArray().Select(f => f!.AsValue().GetValue()).ToArray(); + metaData.Add((Path.GetFileName(filename), + meta["zwstid"]!.AsValue().GetValue(), meta["device"]!.AsValue().GetValue(), + memberCount, memberFilters != null ? string.Join(" / ", memberFilters) : null, + areaComCount, areaComFilters != null ? string.Join(" / ", areaComFilters) : null, + deliveryCount, deliveryFilters != null ? string.Join(" / ", deliveryFilters) : null)); - var wbKgsJson = zip.GetEntry("wb_kgs.json"); - if (wbKgsJson != null) { - using var reader = new StreamReader(wbKgsJson.Open(), Utils.UTF8); - string? line; - while ((line = await reader.ReadLineAsync()) != null) { - var obj = JsonNode.Parse(line)!.AsObject(); - var (k, g) = obj.ToWbKg(currentWbGls); - r.WbKgs.Add(k); - if (g != null) { - currentWbGls[g.GlNr] = g; - r.WbGls.Add(g); + var wbKgsJson = zip.GetEntry("wb_kgs.json"); + if (wbKgsJson != null) { + using var reader = new StreamReader(wbKgsJson.Open(), Utils.UTF8); + string? line; + while ((line = await reader.ReadLineAsync()) != null) { + var obj = JsonNode.Parse(line)!.AsObject(); + var (k, g) = obj.ToWbKg(currentWbGls); + r.WbKgs.Add(k); + if (g != null) { + currentWbGls[g.GlNr] = g; + r.WbGls.Add(g); + } } } - } - 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(); - var (m, b, telNrs, emailAddrs, timestamps) = obj.ToMember(kgs); - r.Members.Add(m); - if (b != null) r.BillingAddresses.Add(b); - r.TelephoneNumbers.AddRange(telNrs); - r.EmailAddresses.AddRange(emailAddrs); - if (timestamps.HasValue) - r.Timestamps["member"].Add((m.MgNr, 0, timestamps.Value.CreatedAt, timestamps.Value.ModifiedAt)); - } - } - - 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(); - var (areaCom, wbrd, timestamps) = obj.ToAreaCom(currentWbRde); - r.AreaCommitments.Add(areaCom); - if (wbrd != null) { - r.Riede.Add(wbrd); + 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(); + var (m, b, telNrs, emailAddrs, timestamps) = obj.ToMember(kgs); + r.Members.Add(m); + if (b != null) r.BillingAddresses.Add(b); + r.TelephoneNumbers.AddRange(telNrs); + r.EmailAddresses.AddRange(emailAddrs); + if (timestamps.HasValue) + r.Timestamps["member"].Add((m.MgNr, 0, timestamps.Value.CreatedAt, timestamps.Value.ModifiedAt)); } - if (timestamps.HasValue) - r.Timestamps["area_commitment"].Add((areaCom.FbNr, 0, timestamps.Value.CreatedAt, timestamps.Value.ModifiedAt)); } - } - 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, rde, timestamps) = obj.ToDelivery(currentLsNrs, currentDids, kgs, currentWbRde); - r.Deliveries.Add(d); - r.DeliveryParts.AddRange(parts); - r.Modifiers.AddRange(mods); - r.Riede.AddRange(rde); - if (timestamps.HasValue) - r.Timestamps["delivery"].Add((d.Year, d.DId, timestamps.Value.CreatedAt, timestamps.Value.ModifiedAt)); + 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(); + var (areaCom, wbrd, timestamps) = obj.ToAreaCom(currentWbRde); + r.AreaCommitments.Add(areaCom); + if (wbrd != null) { + r.Riede.Add(wbrd); + } + if (timestamps.HasValue) + r.Timestamps["area_commitment"].Add((areaCom.FbNr, 0, timestamps.Value.CreatedAt, timestamps.Value.ModifiedAt)); + } + } + + 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, rde, timestamps) = obj.ToDelivery(currentLsNrs, currentDids, kgs, currentWbRde); + r.Deliveries.Add(d); + r.DeliveryParts.AddRange(parts); + r.Modifiers.AddRange(mods); + r.Riede.AddRange(rde); + if (timestamps.HasValue) + r.Timestamps["delivery"].Add((d.Year, d.DId, timestamps.Value.CreatedAt, timestamps.Value.ModifiedAt)); + } + } + } catch (Exception exc) when ( + exc is InvalidDataException || + exc is FileFormatException || + exc is FileNotFoundException || + exc is IOException) { + data.RemoveAt(data.Count - 1); + var str = $"Die Elwig-Export-Datei '{Path.GetFileName(filename)}' konnte nicht verarbeitet werden und wird übersprungen.\n\n" + exc.Message; + if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message; + MessageBox.Show(str, "Fehler beim Importieren", MessageBoxButton.OK, MessageBoxImage.Error); + await AddImportedFiles(Path.GetFileName(filename)); + } catch (Exception exc) { + data.RemoveAt(data.Count - 1); + var str = $"Die Elwig-Export-Datei '{Path.GetFileName(filename)}' konnte nicht verarbeitet werden. Soll sie in Zukunft übersprungen werden?\n\n" + exc.Message; + if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message; + var r = MessageBox.Show(str, "Fehler beim Importieren", MessageBoxButton.YesNo, MessageBoxImage.Error, MessageBoxResult.No); + if (r == MessageBoxResult.Yes) { + await AddImportedFiles(Path.GetFileName(filename)); } } }