From dd568b81e87ddf7554294e9f8a62d66646e7d5d1 Mon Sep 17 00:00:00 2001
From: Lorenz Stechauner <lorenz.stechauner@necronda.net>
Date: Sat, 27 Jan 2024 11:08:10 +0100
Subject: [PATCH] Billing: Rename attributeVariants and contracts to vaributes

---
 Elwig/Helpers/Billing/BillingData.cs          | 30 ++++++++--------
 Elwig/Helpers/Billing/BillingVariant.cs       |  2 +-
 Elwig/Helpers/Billing/EditBillingData.cs      | 18 +++++-----
 Elwig/Helpers/Billing/GraphEntry.cs           | 18 +++++-----
 Elwig/Helpers/Billing/PaymentBillingData.cs   | 16 ++++-----
 .../{ContractSelection.cs => Varibute.cs}     |  6 ++--
 Elwig/Helpers/Utils.cs                        |  8 ++---
 Elwig/Windows/ChartWindow.xaml                |  6 ++--
 Elwig/Windows/ChartWindow.xaml.cs             | 36 +++++++++----------
 Tests/HelperTests/BillingDataTest.cs          | 22 ++++++------
 10 files changed, 81 insertions(+), 81 deletions(-)
 rename Elwig/Helpers/Billing/{ContractSelection.cs => Varibute.cs} (75%)

diff --git a/Elwig/Helpers/Billing/BillingData.cs b/Elwig/Helpers/Billing/BillingData.cs
index 87bc21a..9c16a78 100644
--- a/Elwig/Helpers/Billing/BillingData.cs
+++ b/Elwig/Helpers/Billing/BillingData.cs
@@ -150,15 +150,15 @@ namespace Elwig.Helpers.Billing {
             return dict;
         }
 
-        protected static Dictionary<string, JsonValue> GetSelection(JsonNode value, IEnumerable<string> attributeVariants) {
+        protected static Dictionary<string, JsonValue> GetSelection(JsonNode value, IEnumerable<string> vaributes) {
             if (value is JsonValue flatRate) {
-                return attributeVariants.ToDictionary(e => e, _ => flatRate);
+                return vaributes.ToDictionary(e => e, _ => flatRate);
             } if (value is not JsonObject data) {
                 throw new InvalidOperationException();
             }
             Dictionary<string, JsonValue> dict;
             if (data["default"] is JsonValue def) {
-                dict = attributeVariants.ToDictionary(e => e, _ => def);
+                dict = vaributes.ToDictionary(e => e, _ => def);
             } else {
                 dict = [];
             }
@@ -168,13 +168,13 @@ namespace Elwig.Helpers.Billing {
             var others = data.Where(p => !p.Key.StartsWith('/') && p.Key.Length > 2 && p.Key != "default");
             foreach (var (idx, v) in variants) {
                 var curve = v?.AsValue() ?? throw new InvalidOperationException();
-                foreach (var i in attributeVariants.Where(e => e.StartsWith(idx[..^1]))) {
+                foreach (var i in vaributes.Where(e => e.StartsWith(idx[..^1]))) {
                     dict[i] = curve;
                 }
             }
             foreach (var (idx, v) in attributes) {
                 var curve = v?.AsValue() ?? throw new InvalidOperationException();
-                foreach (var i in attributeVariants.Where(e => e[2..] == idx[1..])) {
+                foreach (var i in vaributes.Where(e => e[2..] == idx[1..])) {
                     dict[i] = curve;
                 }
             }
@@ -257,7 +257,7 @@ namespace Elwig.Helpers.Billing {
             return curve;
         }
 
-        protected static void CollapsePaymentData(JsonObject data, IEnumerable<string> attributeVariants) {
+        protected static void CollapsePaymentData(JsonObject data, IEnumerable<string> vaributes) {
             Dictionary<string, List<string>> rev1 = [];
             Dictionary<decimal, List<string>> rev2 = [];
             foreach (var (k, v) in data) {
@@ -273,18 +273,18 @@ namespace Elwig.Helpers.Billing {
             }
             if (!data.ContainsKey("default")) {
                 foreach (var (v, ks) in rev1) {
-                    if (ks.Count >= attributeVariants.Count() / 2.0) {
+                    if (ks.Count >= vaributes.Count() / 2.0) {
                         foreach (var k in ks) data.Remove(k);
                         data["default"] = v;
-                        CollapsePaymentData(data, attributeVariants);
+                        CollapsePaymentData(data, vaributes);
                         return;
                     }
                 }
                 foreach (var (v, ks) in rev2) {
-                    if (ks.Count >= attributeVariants.Count() / 2.0) {
+                    if (ks.Count >= vaributes.Count() / 2.0) {
                         foreach (var k in ks) data.Remove(k);
                         data["default"] = v;
-                        CollapsePaymentData(data, attributeVariants);
+                        CollapsePaymentData(data, vaributes);
                         return;
                     }
                 }
@@ -296,7 +296,7 @@ namespace Elwig.Helpers.Billing {
                 .Distinct()
                 .ToList();
             foreach (var idx in attributes) {
-                var len = attributeVariants.Count(e => e.EndsWith(idx));
+                var len = vaributes.Count(e => e.EndsWith(idx));
                 foreach (var (v, ks) in rev1) {
                     var myKs = ks.Where(k => k.EndsWith(idx)).ToList();
                     if (myKs.Count > 1 && myKs.Count >= len / 2.0) {
@@ -314,7 +314,7 @@ namespace Elwig.Helpers.Billing {
             }
         }
 
-        public static JsonObject FromGraphEntries(IEnumerable<GraphEntry> graphEntries, BillingData? origData = null, IEnumerable<string>? attributeVariants = null) {
+        public static JsonObject FromGraphEntries(IEnumerable<GraphEntry> graphEntries, BillingData? origData = null, IEnumerable<string>? vaributes = null) {
             var payment = new JsonObject();
             var qualityWei = new JsonObject();
             var curves = new JsonArray();
@@ -331,7 +331,7 @@ namespace Elwig.Helpers.Billing {
                 } else {
                     continue;
                 }
-                foreach (var c in entry.Contracts) {
+                foreach (var c in entry.Vaributes) {
                     if (entry.Abgewertet) {
                         qualityWei[$"{c.Variety?.SortId}/{c.Attribute?.AttrId}"] = node.DeepClone();
                     } else {
@@ -340,8 +340,8 @@ namespace Elwig.Helpers.Billing {
                 }
             }
 
-            CollapsePaymentData(payment, attributeVariants ?? payment.Select(e => e.Key).ToList());
-            CollapsePaymentData(qualityWei, attributeVariants ?? qualityWei.Select(e => e.Key).ToList());
+            CollapsePaymentData(payment, vaributes ?? payment.Select(e => e.Key).ToList());
+            CollapsePaymentData(qualityWei, vaributes ?? qualityWei.Select(e => e.Key).ToList());
 
             var data = new JsonObject {
                 ["mode"] = "elwig",
diff --git a/Elwig/Helpers/Billing/BillingVariant.cs b/Elwig/Helpers/Billing/BillingVariant.cs
index c1b8506..b913241 100644
--- a/Elwig/Helpers/Billing/BillingVariant.cs
+++ b/Elwig/Helpers/Billing/BillingVariant.cs
@@ -15,7 +15,7 @@ namespace Elwig.Helpers.Billing {
         public BillingVariant(int year, int avnr) : base(year) {
             AvNr = avnr;
             PaymentVariant = Context.PaymentVariants.Find(Year, AvNr) ?? throw new ArgumentException("PaymentVar not found");
-            Data = PaymentBillingData.FromJson(PaymentVariant.Data, Utils.GetAttributeVarieties(Context, Year, onlyDelivered: false));
+            Data = PaymentBillingData.FromJson(PaymentVariant.Data, Utils.GetVaributes(Context, Year, onlyDelivered: false));
         }
 
         public async Task Calculate() {
diff --git a/Elwig/Helpers/Billing/EditBillingData.cs b/Elwig/Helpers/Billing/EditBillingData.cs
index cac12e5..5824b56 100644
--- a/Elwig/Helpers/Billing/EditBillingData.cs
+++ b/Elwig/Helpers/Billing/EditBillingData.cs
@@ -7,15 +7,15 @@ using System.Text.Json.Nodes;
 namespace Elwig.Helpers.Billing {
     public class EditBillingData : BillingData {
 
-        protected readonly IEnumerable<string> AttributeVariants;
+        protected readonly IEnumerable<string> Vaributes;
 
-        public EditBillingData(JsonObject data, IEnumerable<string> attributeVariants) :
+        public EditBillingData(JsonObject data, IEnumerable<string> vaributes) :
             base(data) {
-            AttributeVariants = attributeVariants;
+            Vaributes = vaributes;
         }
 
-        public static EditBillingData FromJson(string json, IEnumerable<string> attributeVariants) {
-            return new(ParseJson(json), attributeVariants);
+        public static EditBillingData FromJson(string json, IEnumerable<string> vaributes) {
+            return new(ParseJson(json), vaributes);
         }
 
         private (Dictionary<int, Curve>, Dictionary<int, List<string>>) GetGraphEntries(JsonNode root) {
@@ -56,7 +56,7 @@ namespace Elwig.Helpers.Billing {
             }
 
             Dictionary<int, List<string>> dict3 = curves.ToDictionary(c => c.Key, _ => new List<string>());
-            foreach (var (selector, value) in GetSelection(root, AttributeVariants)) {
+            foreach (var (selector, value) in GetSelection(root, Vaributes)) {
                 int? idx = null;
                 if (value.TryGetValue<decimal>(out var val)) {
                     idx = Array.IndexOf(virtCurves, val) + virtOffset;
@@ -75,7 +75,7 @@ namespace Elwig.Helpers.Billing {
             var attrs = ctx.WineAttributes.ToDictionary(a => a.AttrId, a => a);
             return entries
                 .Select(e => new GraphEntry(e.Key, precision, curves[e.Key], e.Value
-                    .Select(s => new ContractSelection(vars[s[..2]], s.Length > 2 ? attrs[s[2..]] : null))
+                    .Select(s => new Varibute(vars[s[..2]], s.Length > 2 ? attrs[s[2..]] : null))
                     .ToList()))
                 .ToList();
         }
@@ -83,7 +83,7 @@ namespace Elwig.Helpers.Billing {
         public IEnumerable<GraphEntry> GetPaymentGraphEntries(AppDbContext ctx, Season season) {
             var root = GetPaymentEntry();
             var (curves, entries) = GetGraphEntries(root);
-            return CreateGraphEntries(ctx, season.Precision, curves, entries).Where(e => e.Contracts.Count > 0);
+            return CreateGraphEntries(ctx, season.Precision, curves, entries).Where(e => e.Vaributes.Count > 0);
         }
 
         public IEnumerable<GraphEntry> GetQualityGraphEntries(AppDbContext ctx, Season season, int idOffset = 0) {
@@ -91,7 +91,7 @@ namespace Elwig.Helpers.Billing {
             if (root == null || root["WEI"] is not JsonNode qualityWei)
                 return [];
             var (curves, entries) = GetGraphEntries(qualityWei);
-            var list = CreateGraphEntries(ctx, season.Precision, curves, entries).Where(e => e.Contracts.Count > 0);
+            var list = CreateGraphEntries(ctx, season.Precision, curves, entries).Where(e => e.Vaributes.Count > 0);
             foreach (var e in list) {
                 e.Id += idOffset;
                 e.Abgewertet = true;
diff --git a/Elwig/Helpers/Billing/GraphEntry.cs b/Elwig/Helpers/Billing/GraphEntry.cs
index e1098a2..1b0bd74 100644
--- a/Elwig/Helpers/Billing/GraphEntry.cs
+++ b/Elwig/Helpers/Billing/GraphEntry.cs
@@ -36,10 +36,10 @@ namespace Elwig.Helpers.Billing {
             }
         }
 
-        public List<ContractSelection> Contracts { get; set; }
-        public string ContractsStringSimple => (Abgewertet ? "Abgew.: " : "") + (Contracts.Count != 0 ? (Contracts.Count >= 25 ? "Restliche Sorten" : string.Join(", ", Contracts.Select(c => c.Listing))) : "-");
-        public string ContractsString => Contracts.Count != 0 ? string.Join("\n", Contracts.Select(c => c.FullName)) : "-";
-        public string ContractsStringChange => (Abgewertet ? "A." : "") + string.Join(",", Contracts.Select(c => c.Listing));
+        public List<Varibute> Vaributes { get; set; }
+        public string VaributeStringSimple => (Abgewertet ? "Abgew.: " : "") + (Vaributes.Count != 0 ? (Vaributes.Count >= 25 ? "Restliche Sorten" : string.Join(", ", Vaributes.Select(c => c.Listing))) : "-");
+        public string VaributeString => Vaributes.Count != 0 ? string.Join("\n", Vaributes.Select(c => c.FullName)) : "-";
+        public string VaributeStringChange => (Abgewertet ? "A." : "") + string.Join(",", Vaributes.Select(c => c.Listing));
         private readonly int Precision;
 
         public GraphEntry(int id, int precision, BillingData.CurveMode mode) {
@@ -47,7 +47,7 @@ namespace Elwig.Helpers.Billing {
             Precision = precision;
             Mode = mode;
             DataGraph = new Graph(precision, MinX, MaxX); ;
-            Contracts = [];
+            Vaributes = [];
         }
 
         public GraphEntry(int id, int precision, BillingData.CurveMode mode, Dictionary<double, decimal> data, Dictionary<double, decimal>? gebunden) :
@@ -56,21 +56,21 @@ namespace Elwig.Helpers.Billing {
             if (gebunden != null) GebundenGraph = new Graph(gebunden, precision, MinXGeb, MaxX);
         }
 
-        public GraphEntry(int id, int precision, BillingData.Curve curve, List<ContractSelection> contracts) :
+        public GraphEntry(int id, int precision, BillingData.Curve curve, List<Varibute> vaributes) :
             this(id, precision, curve.Mode) {
             DataGraph = new Graph(curve.Normal, precision, MinX, MaxX);
             if (curve.Gebunden != null)
                 GebundenGraph = new Graph(curve.Gebunden, precision, MinXGeb, MaxX);
-            Contracts = contracts;
+            Vaributes = vaributes;
         }
 
-        private GraphEntry(int id, int precision, BillingData.CurveMode mode, Graph dataGraph, Graph? gebundenGraph, List<ContractSelection> contracts) {
+        private GraphEntry(int id, int precision, BillingData.CurveMode mode, Graph dataGraph, Graph? gebundenGraph, List<Varibute> vaributes) {
             Id = id;
             Precision = precision;
             Mode = mode;
             DataGraph = dataGraph;
             GebundenGraph = gebundenGraph;
-            Contracts = contracts;
+            Vaributes = vaributes;
         }
 
         public void AddGebundenGraph() {
diff --git a/Elwig/Helpers/Billing/PaymentBillingData.cs b/Elwig/Helpers/Billing/PaymentBillingData.cs
index b906408..ba33ed1 100644
--- a/Elwig/Helpers/Billing/PaymentBillingData.cs
+++ b/Elwig/Helpers/Billing/PaymentBillingData.cs
@@ -9,24 +9,24 @@ namespace Elwig.Helpers.Billing {
         protected readonly Dictionary<int, Curve> Curves;
         protected readonly Dictionary<string, Curve> PaymentData;
         protected readonly Dictionary<string, Curve> QualityData;
-        protected readonly IEnumerable<string> AttributeVariants;
+        protected readonly IEnumerable<string> Vaributes;
 
-        public PaymentBillingData(JsonObject data, IEnumerable<string> attributeVariants) :
+        public PaymentBillingData(JsonObject data, IEnumerable<string> vaributes) :
             base(data) {
-            if (attributeVariants.Any(e => e.Any(c => c < 'A' || c > 'Z')))
-                throw new ArgumentException("Invalid attributeVariants");
-            AttributeVariants = attributeVariants;
+            if (vaributes.Any(e => e.Any(c => c < 'A' || c > 'Z')))
+                throw new ArgumentException("Invalid vaributes");
+            Vaributes = vaributes;
             Curves = GetCurves();
             PaymentData = GetPaymentData();
             QualityData = GetQualityData();
         }
 
-        public static PaymentBillingData FromJson(string json, IEnumerable<string> attributeVariants) {
-            return new(ParseJson(json), attributeVariants);
+        public static PaymentBillingData FromJson(string json, IEnumerable<string> vaributes) {
+            return new(ParseJson(json), vaributes);
         }
 
         private Dictionary<string, Curve> GetData(JsonNode data) {
-            return GetSelection(data, AttributeVariants).ToDictionary(e => e.Key, e => LookupCurve(e.Value));
+            return GetSelection(data, Vaributes).ToDictionary(e => e.Key, e => LookupCurve(e.Value));
         }
 
         protected Dictionary<string, Curve> GetPaymentData() {
diff --git a/Elwig/Helpers/Billing/ContractSelection.cs b/Elwig/Helpers/Billing/Varibute.cs
similarity index 75%
rename from Elwig/Helpers/Billing/ContractSelection.cs
rename to Elwig/Helpers/Billing/Varibute.cs
index 8479958..d75326c 100644
--- a/Elwig/Helpers/Billing/ContractSelection.cs
+++ b/Elwig/Helpers/Billing/Varibute.cs
@@ -2,14 +2,14 @@
 using System;
 
 namespace Elwig.Helpers.Billing {
-    public class ContractSelection : IComparable<ContractSelection> {
+    public class Varibute : IComparable<Varibute> {
 
         public WineVar? Variety { get; }
         public WineAttr? Attribute { get; }
         public string Listing => $"{Variety?.SortId}{Attribute?.AttrId}";
         public string FullName => $"{Variety?.Name}" + (Variety != null && Attribute != null ? " " : "") + $"{Attribute?.Name}";
 
-        public ContractSelection(WineVar? var, WineAttr? attr) {
+        public Varibute(WineVar? var, WineAttr? attr) {
             Variety = var;
             Attribute = attr;
         }
@@ -18,7 +18,7 @@ namespace Elwig.Helpers.Billing {
             return Listing;
         }
 
-        public int CompareTo(ContractSelection? other) {
+        public int CompareTo(Varibute? other) {
             return Listing.CompareTo(other?.Listing);
         } 
     }
diff --git a/Elwig/Helpers/Utils.cs b/Elwig/Helpers/Utils.cs
index b4107e7..84bf92a 100644
--- a/Elwig/Helpers/Utils.cs
+++ b/Elwig/Helpers/Utils.cs
@@ -362,7 +362,7 @@ namespace Elwig.Helpers {
             return output.OrderByDescending(l => l.Count());
         }
 
-        public static List<string> GetAttributeVarieties(AppDbContext ctx, int year, bool withSlash = false, bool onlyDelivered = true) {
+        public static List<string> GetVaributes(AppDbContext ctx, int year, bool withSlash = false, bool onlyDelivered = true) {
             var varieties = ctx.WineVarieties.Select(v => v.SortId).ToList();
             var delivered = ctx.DeliveryParts
                .Where(d => d.Year == year)
@@ -372,11 +372,11 @@ namespace Elwig.Helpers {
             return [.. (onlyDelivered ? delivered : delivered.Union(varieties)).Order()];
         }
 
-        public static List<ContractSelection> GetContractsForYear(AppDbContext ctx, int year, bool onlyDelivered = true) {
+        public static List<Varibute> GetVaributesForYear(AppDbContext ctx, int year, bool onlyDelivered = true) {
             var varieties = ctx.WineVarieties.ToDictionary(v => v.SortId, v => v);
             var attributes = ctx.WineAttributes.ToDictionary(a => a.AttrId, a => a);
-            return GetAttributeVarieties(ctx, year, false, onlyDelivered)
-                .Select(s => new ContractSelection(varieties[s[..2]], s.Length > 2 ? attributes[s[2..]] : null))
+            return GetVaributes(ctx, year, false, onlyDelivered)
+                .Select(s => new Varibute(varieties[s[..2]], s.Length > 2 ? attributes[s[2..]] : null))
                 .ToList();
         }
     }
diff --git a/Elwig/Windows/ChartWindow.xaml b/Elwig/Windows/ChartWindow.xaml
index 7e2eeda..0118912 100644
--- a/Elwig/Windows/ChartWindow.xaml
+++ b/Elwig/Windows/ChartWindow.xaml
@@ -61,8 +61,8 @@
             </Grid.ColumnDefinitions>
 
             <Label Content="Für:" Margin="10,-2,0,0" FontSize="14" Grid.Column="0" VerticalAlignment="Center"/>
-            <xctk:CheckComboBox x:Name="ContractInput" Margin="50,0,0,0" Grid.Column="0"
-                                Delimiter=", " AllItemsSelectedContent="Alle" IsEnabled="False" ItemSelectionChanged="ContractInput_Changed"
+            <xctk:CheckComboBox x:Name="VaributeInput" Margin="50,0,0,0" Grid.Column="0"
+                                Delimiter=", " AllItemsSelectedContent="Alle" IsEnabled="False" ItemSelectionChanged="VaributeInput_Changed"
                                 Width="500" Height="25" HorizontalAlignment="Left">
                 <xctk:CheckComboBox.ItemTemplate>
                     <DataTemplate>
@@ -83,7 +83,7 @@
                 <DataTemplate>
                     <StackPanel Orientation="Horizontal">
                         <TextBlock Text="{Binding Id}" Width="30"/>
-                        <TextBlock Text="{Binding ContractsStringSimple}" ToolTip="{Binding ContractsString}"/>
+                        <TextBlock Text="{Binding VaributeStringSimple}" ToolTip="{Binding VaributeString}"/>
                     </StackPanel>
                 </DataTemplate>
             </ListBox.ItemTemplate>
diff --git a/Elwig/Windows/ChartWindow.xaml.cs b/Elwig/Windows/ChartWindow.xaml.cs
index 88b70a3..a4295f9 100644
--- a/Elwig/Windows/ChartWindow.xaml.cs
+++ b/Elwig/Windows/ChartWindow.xaml.cs
@@ -84,18 +84,18 @@ namespace Elwig.Windows {
             PaymentVar = await Context.PaymentVariants.FindAsync(Year, AvNr) ?? throw new ArgumentException("PaymentVar not found");
             Season = await Context.Seasons.FindAsync(Year) ?? throw new ArgumentException("Season not found");
 
-            var data = EditBillingData.FromJson(PaymentVar.Data, Utils.GetAttributeVarieties(Context, Year));
+            var data = EditBillingData.FromJson(PaymentVar.Data, Utils.GetVaributes(Context, Year));
             var paymentEntries = data.GetPaymentGraphEntries(Context, Season);
             GraphEntries = [
                 ..paymentEntries,
                 ..data.GetQualityGraphEntries(Context, Season, paymentEntries.Max(e => e.Id))
             ];
 
-            var contracts = Utils.GetContractsForYear(Context, Year);
+            var vaributes = Utils.GetVaributesForYear(Context, Year);
             FillingInputs = true;
-            ControlUtils.RenewItemsSource(ContractInput, contracts, g => (g as ContractSelection)?.Listing);
+            ControlUtils.RenewItemsSource(VaributeInput, vaributes, g => (g as Varibute)?.Listing);
             FillingInputs = false;
-            ControlUtils.RenewItemsSource(GraphList, GraphEntries, g => (g as GraphEntry)?.ContractsStringChange, GraphList_SelectionChanged, ControlUtils.RenewSourceDefault.First);
+            ControlUtils.RenewItemsSource(GraphList, GraphEntries, g => (g as GraphEntry)?.VaributeStringChange, GraphList_SelectionChanged, ControlUtils.RenewSourceDefault.First);
 
             RefreshInputs();
         }
@@ -108,7 +108,7 @@ namespace Elwig.Windows {
                 GebundenTypeFixed.IsEnabled = true;
                 GebundenTypeGraph.IsEnabled = true;
                 GebundenTypeNone.IsEnabled = true;
-                ContractInput.IsEnabled = true;
+                VaributeInput.IsEnabled = true;
                 AbgewertetInput.IsEnabled = true;
                 EnableOptionButtons();
                 FillInputs();
@@ -127,7 +127,7 @@ namespace Elwig.Windows {
                 GebundenTypeFixed.IsEnabled = false;
                 GebundenTypeGraph.IsEnabled = false;
                 GebundenTypeNone.IsEnabled = false;
-                ContractInput.IsEnabled = false;
+                VaributeInput.IsEnabled = false;
                 AbgewertetInput.IsEnabled = false;
             }
             GC.Collect();
@@ -148,7 +148,7 @@ namespace Elwig.Windows {
                 GebundenFlatBonus.Text = "";
             }
 
-            ControlUtils.SelectCheckComboBoxItems(ContractInput, SelectedGraphEntry?.Contracts ?? [], i => (i as ContractSelection)?.Listing);
+            ControlUtils.SelectCheckComboBoxItems(VaributeInput, SelectedGraphEntry?.Vaributes ?? [], i => (i as Varibute)?.Listing);
 
             InitPlot();
             OechslePricePlot.IsEnabled = true;
@@ -622,7 +622,7 @@ namespace Elwig.Windows {
             if (SelectedGraphEntry == null) return;
 
             var r = MessageBox.Show(
-                $"Soll der Graph {SelectedGraphEntry.Id} (verwendet in folgenden Verträgen: {SelectedGraphEntry.ContractsStringSimple}) wirklich gelöscht werden?",
+                $"Soll der Graph {SelectedGraphEntry.Id} (verwendet in folgenden Verträgen: {SelectedGraphEntry.VaributeStringSimple}) wirklich gelöscht werden?",
                 "Graph löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
 
             if (r == MessageBoxResult.Yes) {
@@ -635,7 +635,7 @@ namespace Elwig.Windows {
 
         private async void SaveButton_Click(object sender, RoutedEventArgs e) {
             var origData = BillingData.FromJson(PaymentVar.Data);
-            var data = BillingData.FromGraphEntries(GraphEntries, origData, Utils.GetAttributeVarieties(Context, Year, withSlash: true));
+            var data = BillingData.FromGraphEntries(GraphEntries, origData, Utils.GetVaributes(Context, Year, withSlash: true));
 
             EntityEntry<PaymentVar>? tr = null;
             try {
@@ -715,32 +715,32 @@ namespace Elwig.Windows {
             }
         }
 
-        private void ContractInput_Changed(object sender, ItemSelectionChangedEventArgs e) {
+        private void VaributeInput_Changed(object sender, ItemSelectionChangedEventArgs e) {
             if (FillingInputs) return;
             if (e.IsSelected == true) {
-                bool success = RemoveContractFromOtherGraphEntries(e.Item.ToString());
+                bool success = RemoveVaributeFromOtherGraphEntries(e.Item.ToString());
                 if (!success) {
-                    ContractInput.SelectedItems.Remove(e.Item);
+                    VaributeInput.SelectedItems.Remove(e.Item);
                 }
             }
-            var r = ContractInput.SelectedItems.Cast<ContractSelection>();
-            SelectedGraphEntry!.Contracts = r.ToList();
+            var r = VaributeInput.SelectedItems.Cast<Varibute>();
+            SelectedGraphEntry!.Vaributes = r.ToList();
             SetHasChanged();
             GraphList.Items.Refresh();
         }
 
-        private bool RemoveContractFromOtherGraphEntries(string? contract) {
-            if (contract == null) return true;
+        private bool RemoveVaributeFromOtherGraphEntries(string? varibute) {
+            if (varibute == null) return true;
             foreach (var ge in GraphEntries) {
                 if (ge != SelectedGraphEntry && ge.Abgewertet == SelectedGraphEntry?.Abgewertet) {
-                    var toRemove = ge.Contracts.Where(c => c.Listing.Equals(contract)).ToList();
+                    var toRemove = ge.Vaributes.Where(c => c.Listing.Equals(varibute)).ToList();
                     if (toRemove.Count == 0) continue;
                     var r = MessageBox.Show($"Achtung: {string.Join(", ", toRemove)} ist bereits in Graph {ge.Id} in Verwendung!\nSoll die Zuweisung dort entfernt werden?", "Entfernen bestätigen",
                         MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
                     if (r != MessageBoxResult.Yes) {
                         return false;
                     }
-                    ge.Contracts.RemoveAll(c => c.Listing.Equals(contract));
+                    ge.Vaributes.RemoveAll(c => c.Listing.Equals(varibute));
                 }
             }
             return true;
diff --git a/Tests/HelperTests/BillingDataTest.cs b/Tests/HelperTests/BillingDataTest.cs
index 2c4b053..1224b29 100644
--- a/Tests/HelperTests/BillingDataTest.cs
+++ b/Tests/HelperTests/BillingDataTest.cs
@@ -8,7 +8,7 @@ namespace Tests.HelperTests {
     public class BillingDataTest {
 
         private static readonly JsonSerializerOptions JsonOpts = new() { WriteIndented = true };
-        private static readonly string[] AttributeVariants = ["GV", "GVD", "GVK", "GVS", "GVZ", "WR", "WRS", "ZW", "ZWS", "ZWZ"];
+        private static readonly string[] Vaributes = ["GV", "GVD", "GVK", "GVS", "GVZ", "WR", "WRS", "ZW", "ZWS", "ZWZ"];
 
         [OneTimeSetUp]
         public async Task SetupBilling() {
@@ -52,7 +52,7 @@ namespace Tests.HelperTests {
                   "payment": 0.5,
                   "curves": []
                 }
-                """, AttributeVariants);
+                """, Vaributes);
             Assert.Multiple(() => {
                 TestCalcOe(data, "GV",  73, 0.5m);
                 TestCalcOe(data, "WRS", 74, 0.5m);
@@ -77,7 +77,7 @@ namespace Tests.HelperTests {
                     "geb": 0.10
                   }]
                 }
-                """, AttributeVariants);
+                """, Vaributes);
             Assert.Multiple(() => {
                 TestCalcOe(data, "GV", 70, 0.25m);
                 TestCalcOe(data, "GV", 72, 0.25m);
@@ -114,7 +114,7 @@ namespace Tests.HelperTests {
                     }
                   }]
                 }
-                """, AttributeVariants);
+                """, Vaributes);
             Assert.Multiple(() => {
                 TestCalcKmw(data, "GV", 13.00, 0.10m);
                 TestCalcKmw(data, "GV", 13.50, 0.10m);
@@ -148,7 +148,7 @@ namespace Tests.HelperTests {
                   },
                   "curves": []
                 }
-                """, AttributeVariants);
+                """, Vaributes);
             Assert.Multiple(() => {
                 TestCalcOe(data, "WR",  73, 0.10m);
                 TestCalcOe(data, "WRS", 73, 0.15m);
@@ -179,7 +179,7 @@ namespace Tests.HelperTests {
                   },
                   "curves": []
                 }
-                """, AttributeVariants);
+                """, Vaributes);
             Assert.Multiple(() => {
                 TestCalcOe(data, "GV",  75, 0.30m, qualid: "WEI");
                 TestCalcOe(data, "ZW",  76, 0.25m, qualid: "WEI");
@@ -221,7 +221,7 @@ namespace Tests.HelperTests {
                     }
                   }]
                 }
-                """, AttributeVariants);
+                """, Vaributes);
             Assert.Multiple(() => {
                 TestCalcKmw(data, "GV", 15.0, 2.0m);
                 TestCalcKmw(data, "GV", 15.5, 2.272727m);
@@ -281,7 +281,7 @@ namespace Tests.HelperTests {
                     }
                   }]
                 }
-                """, AttributeVariants);
+                """, Vaributes);
             Assert.Multiple(() => {
                 TestCalcKmw(data, "GV",  15.0, 0.75m);
                 TestCalcKmw(data, "GVS", 15.0, 0.50m);
@@ -340,7 +340,7 @@ namespace Tests.HelperTests {
                     }
                   }]
                 }
-                """, AttributeVariants);
+                """, Vaributes);
             Assert.Multiple(() => {
                 TestCalcOe(data, "GVK", 73, 0.032m);
                 TestCalcOe(data, "ZWS", 74, 0.033m);
@@ -349,11 +349,11 @@ namespace Tests.HelperTests {
             });
         }
 
-        private static List<ContractSelection> GetSelection(IEnumerable<string> attVars) {
+        private static List<Varibute> GetSelection(IEnumerable<string> attVars) {
             return attVars.Select(s => {
                 var sortid = s[..2];
                 var attrid = s.Length > 2 ? s[2..] : null;
-                return new ContractSelection(
+                return new Varibute(
                     new WineVar(sortid, sortid),
                     attrid == null ? null : new WineAttr(attrid, attrid)
                 );