Compare commits

...

21 Commits

Author SHA1 Message Date
lorenz.stechauner 182b367811 ChartWindow: Fix saving bug 2024-01-21 01:20:50 +01:00
lorenz.stechauner a2bb09cfbd Billing: Build BillingData-Json in BillingData instead of anywhere else 2024-01-21 00:31:20 +01:00
thomas.hilscher b981b5f895 ChartWindow/Billing: Misc improvements 2024-01-20 19:24:26 +01:00
lorenz.stechauner 9dc2e8a59a Windows: Add Ctrl+P and Ctrl+Shift+P for delivery and member 2024-01-20 15:47:20 +01:00
lorenz.stechauner 1dc05e47cf DeliveryAdminWindow: Use Saison instead of Season in GUI string 2024-01-20 15:32:44 +01:00
lorenz.stechauner 21cc20ee63 Billing/GraphEntry: Use 73 Oe as MinX for gebunden graph 2024-01-20 12:27:01 +01:00
lorenz.stechauner 491c41b239 ChartWindow: Minor bugfixes and polishing 2024-01-20 12:02:50 +01:00
lorenz.stechauner 47658a72ae ChartWindow: Enhance ComboCheckBox 2024-01-20 02:57:22 +01:00
lorenz.stechauner 8b0a4d7979 EditBillingData: Use 140 as upper boundary 2024-01-20 02:43:15 +01:00
lorenz.stechauner 9ee7f6baf1 Billing/Graph: Remove ParseGraphData() 2024-01-20 02:35:59 +01:00
lorenz.stechauner ecbc9c2d82 BillingData: Add GetCurveValueAt(), extracted from PaymentBillingData 2024-01-20 02:33:05 +01:00
lorenz.stechauner bf90543ad8 ChartWindow: Change gebunden color to yellow 2024-01-20 02:09:03 +01:00
lorenz.stechauner 6a5676f916 ChartWindow: Load GraphEntries correctly from EditBillingData 2024-01-20 01:53:27 +01:00
lorenz.stechauner 75e9d756d2 BillingData: Upgrade GetSelection() 2024-01-20 00:48:23 +01:00
lorenz.stechauner ee161b149b BillingData: Extract GetData() from PaymentBillingData into GetSelection() 2024-01-20 00:31:50 +01:00
thomas.hilscher 0cb7b4bfc8 ChartWindow: Added second graph for gebunden 2024-01-19 23:54:16 +01:00
lorenz.stechauner 4a49a17b6a Tests: Update FetchResource target 2024-01-19 16:57:35 +01:00
lorenz.stechauner 741ccaacae Test: Update target once again 2024-01-19 15:50:50 +01:00
lorenz.stechauner 19f4300440 Tests: Add DependsOnTargets 2024-01-19 15:42:32 +01:00
lorenz.stechauner 954c7a8bdb Tests: Change Target to be executed before CoreBuild 2024-01-19 15:38:02 +01:00
lorenz.stechauner 626724fe87 [#29] DeliveryAdminWindow: Only show sums of filtered parts when filtering 2024-01-19 13:35:53 +01:00
13 changed files with 721 additions and 391 deletions
+132 -2
View File
@@ -124,6 +124,7 @@ namespace Elwig.Helpers.Billing {
var obj = c?.AsObject() ?? throw new InvalidOperationException(); var obj = c?.AsObject() ?? throw new InvalidOperationException();
var id = obj["id"]?.GetValue<int>() ?? throw new InvalidOperationException(); var id = obj["id"]?.GetValue<int>() ?? throw new InvalidOperationException();
var cMode = (obj["mode"]?.GetValue<string>() == "kmw") ? CurveMode.Kmw : CurveMode.Oe; var cMode = (obj["mode"]?.GetValue<string>() == "kmw") ? CurveMode.Kmw : CurveMode.Oe;
double quw = cMode == CurveMode.Oe ? 73 : 15;
Dictionary<double, decimal> c1; Dictionary<double, decimal> c1;
Dictionary<double, decimal>? c2 = null; Dictionary<double, decimal>? c2 = null;
@@ -131,7 +132,7 @@ namespace Elwig.Helpers.Billing {
if (norm is JsonObject) { if (norm is JsonObject) {
c1 = GetCurveData(norm.AsObject(), cMode); c1 = GetCurveData(norm.AsObject(), cMode);
} else if (norm?.AsValue().TryGetValue(out decimal v) == true) { } else if (norm?.AsValue().TryGetValue(out decimal v) == true) {
c1 = new() { { cMode == CurveMode.Oe ? 73 : 15, v } }; c1 = new() { { quw, v } };
} else { } else {
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
@@ -139,11 +140,140 @@ namespace Elwig.Helpers.Billing {
if (geb is JsonObject) { if (geb is JsonObject) {
c2 = GetCurveData(geb.AsObject(), cMode); c2 = GetCurveData(geb.AsObject(), cMode);
} else if (geb?.AsValue().TryGetValue(out decimal v) == true) { } else if (geb?.AsValue().TryGetValue(out decimal v) == true) {
c2 = c1.ToDictionary(e => e.Key, e => e.Value + v); var splitVal = GetCurveValueAt(c1, quw);
c2 = c1.ToDictionary(e => e.Key, e => e.Value + (e.Key >= quw ? v : 0));
c2[quw] = splitVal + v;
c2[Math.BitDecrement(quw)] = splitVal;
} }
dict.Add(id, new(cMode, c1, c2)); dict.Add(id, new(cMode, c1, c2));
} }
return dict; return dict;
} }
protected static Dictionary<string, JsonValue> GetSelection(JsonNode value, IEnumerable<string> attributeVariants) {
if (value is JsonValue flatRate) {
return attributeVariants.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);
} else {
dict = [];
}
var variants = data.Where(p => !p.Key.StartsWith('/') && p.Key.Length == 2);
var attributes = data.Where(p => p.Key.StartsWith('/'));
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]))) {
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..])) {
dict[i] = curve;
}
}
foreach (var (idx, v) in others) {
var curve = v?.AsValue() ?? throw new InvalidOperationException();
dict[idx.Replace("/", "")] = curve;
}
return dict;
}
public static decimal GetCurveValueAt(Dictionary<double, decimal> curve, double key) {
if (curve.Count == 1) return curve.First().Value;
var lt = curve.Keys.Where(v => v <= key);
var gt = curve.Keys.Where(v => v >= key);
if (!lt.Any()) {
return curve[gt.Min()];
} else if (!gt.Any()) {
return curve[lt.Max()];
}
var max = lt.Max();
var min = gt.Min();
if (max == min) return curve[key];
var p1 = ((decimal)key - (decimal)min) / ((decimal)max - (decimal)min);
var p2 = 1 - p1;
return curve[min] * p2 + curve[max] * p1;
}
protected static JsonNode GraphToJson(Graph graph, string mode) {
var x = graph.DataX;
var y = graph.DataY;
if (y.Distinct().Count() == 1) {
return JsonValue.Create(graph.DataY[0]);
}
var data = new JsonObject();
if (y[0] != y[1]) {
data.Add(new KeyValuePair<string, JsonNode?>(x[0] + mode, Math.Round(y[0], graph.Precision)));
}
for (int i = 1; i < x.Length - 1; i++) {
if (Math.Round(y[i] - y[i - 1], 10) != Math.Round(y[i + 1] - y[i], 10)) {
data.Add(new KeyValuePair<string, JsonNode?>(x[i] + mode, Math.Round(y[i], graph.Precision)));
}
}
if (y[^1] != y[^2]) {
data.Add(new KeyValuePair<string, JsonNode?>(x[^1] + mode, Math.Round(y[^1], graph.Precision)));
}
return data;
}
protected static JsonObject GraphEntryToJson(GraphEntry entry) {
var curve = new JsonObject {
["id"] = entry.Id,
["mode"] = entry.Mode.ToString().ToLower(),
};
curve["data"] = GraphToJson(entry.DataGraph, entry.Mode.ToString().ToLower());
if (entry.GebundenFlatBonus != null) {
curve["geb"] = entry.GebundenFlatBonus;
} else if (entry.GebundenGraph != null) {
curve["geb"] = GraphToJson(entry.GebundenGraph, entry.Mode.ToString().ToLower());
}
return curve;
}
public JsonObject FromGraphEntries(IEnumerable<GraphEntry> graphEntries) {
var payment = new JsonObject();
var curves = new JsonArray();
foreach (var entry in graphEntries) {
curves.Add(GraphEntryToJson(entry));
foreach (var contract in entry.Contracts) {
payment[$"{contract.Variety?.SortId}/{contract.Attribute?.AttrId}"] = $"curve:{entry.Id}";
}
}
var data = new JsonObject {
["mode"] = "elwig",
["version"] = 1,
};
if (ConsiderDelieryModifiers)
data["consider_delivery_modifiers"] = true;
if (ConsiderContractPenalties)
data["consider_contract_penalties"] = true;
if (ConsiderTotalPenalty)
data["consider_total_penalty"] = true;
if (ConsiderAutoBusinessShares)
data["consider_auto_business_shares"] = true;
data["payment"] = payment;
data["curves"] = curves;
return data;
}
} }
} }
@@ -0,0 +1,39 @@
using Elwig.Models.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Elwig.Helpers.Billing {
public class ContractSelection : IComparable<ContractSelection> {
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) {
Variety = var;
Attribute = attr;
}
public static List<ContractSelection> GetContractsForYear(AppDbContext context, int year) {
return context.DeliveryParts
.Where(p => p.Year == year)
.Select(d => new ContractSelection(d.Variant, d.Attribute))
.Distinct()
.ToList()
.Union(context.WineVarieties.Select(v => new ContractSelection(v, null)))
.DistinctBy(c => c.Listing)
.Order()
.ToList();
}
public override string ToString() {
return Listing;
}
public int CompareTo(ContractSelection? other) {
return Listing.CompareTo(other?.Listing);
}
}
}
+26 -8
View File
@@ -1,4 +1,6 @@
using System.Collections.Generic; using Elwig.Models.Entities;
using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.Json.Nodes; using System.Text.Json.Nodes;
@@ -16,7 +18,7 @@ namespace Elwig.Helpers.Billing {
return new(ParseJson(json), attributeVariants); return new(ParseJson(json), attributeVariants);
} }
public IEnumerable<GraphEntry> GetPaymentGraphEntries() { public IEnumerable<GraphEntry> GetPaymentGraphEntries(AppDbContext context, Season season) {
Dictionary<int, List<string>> dict1 = []; Dictionary<int, List<string>> dict1 = [];
Dictionary<decimal, List<string>> dict2 = []; Dictionary<decimal, List<string>> dict2 = [];
var p = GetPaymentEntry(); var p = GetPaymentEntry();
@@ -40,22 +42,38 @@ namespace Elwig.Helpers.Billing {
dict2[idx].Add("default"); dict2[idx].Add("default");
} }
var virtOffset = dict1.Count;
Dictionary<int, Curve> curves = GetCurves(); Dictionary<int, Curve> curves = GetCurves();
decimal[] virtCurves = [.. dict2.Keys.Order()]; decimal[] virtCurves = [.. dict2.Keys.Order()];
for (int i = 0; i < virtCurves.Length; i++) { for (int i = 0; i < virtCurves.Length; i++) {
var idx = virtCurves[i]; var idx = virtCurves[i];
dict1[1000 + i] = dict2[idx]; dict1[i + virtOffset] = dict2[idx];
curves[1000 + i] = new Curve(CurveMode.Oe, new() { { 73, idx } }, null); curves[i + virtOffset] = new Curve(CurveMode.Oe, new() { { 73, idx } }, null);
} }
Dictionary<int, List<string>> dict3 = []; Dictionary<int, List<string>> dict3 = curves.ToDictionary(c => c.Key, _ => new List<string>());
foreach (var (selector, value) in GetSelection(p, AttributeVariants)) {
int? idx = null;
if (value.TryGetValue<decimal>(out var val)) {
idx = Array.IndexOf(virtCurves, val) + virtOffset;
} else if (value.TryGetValue<string>(out var str)) {
idx = int.Parse(str.Split(":")[1]);
}
if (idx != null)
dict3[(int)idx].Add(selector);
}
var vars = context.WineVarieties.ToDictionary(v => v.SortId, v => v);
var attrs = context.WineAttributes.ToDictionary(a => a.AttrId, a => a);
return dict3
return dict3.Select(e => new GraphEntry(e.Key, curves[e.Key], 50, 120)).ToList(); .Select(e => new GraphEntry(e.Key, season.Precision, curves[e.Key], e.Value
.Select(s => new ContractSelection(vars[s[..2]], s.Length > 2 ? attrs[s[2..]] : null))
.ToList(), 50, 73, 140))
.ToList();
} }
public IEnumerable<GraphEntry> GetQualityGraphEntries() { public IEnumerable<GraphEntry> GetQualityGraphEntries(AppDbContext context, Season season) {
Dictionary<int, List<string>> dict1 = []; Dictionary<int, List<string>> dict1 = [];
Dictionary<decimal, List<string>> dict2 = []; Dictionary<decimal, List<string>> dict2 = [];
foreach (var (qualid, q) in GetQualityEntry() ?? []) { foreach (var (qualid, q) in GetQualityEntry() ?? []) {
+54 -65
View File
@@ -2,106 +2,95 @@ using ScottPlot;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.Json.Nodes;
namespace Elwig.Helpers.Billing { namespace Elwig.Helpers.Billing {
public class Graph : ICloneable { public class Graph : ICloneable {
public readonly int Precision;
public double[] DataX { get; set; } public double[] DataX { get; set; }
public double[] DataY { get; set; } public double[] DataY { get; set; }
public int MinX { get; set; }
public int MaxX { get; set; }
public Graph(int minX, int maxX) { public Graph(int precision, int minX, int maxX) {
Precision = precision;
MinX = minX;
MaxX = maxX;
DataX = DataGen.Range(minX, maxX + 1); DataX = DataGen.Range(minX, maxX + 1);
DataY = DataGen.Zeros(maxX - minX + 1); DataY = DataGen.Zeros(maxX - minX + 1);
} }
public Graph(Dictionary<double, decimal> data, int minX, int maxX) { public Graph(Dictionary<double, decimal> data, int precision, int minX, int maxX) {
Precision = precision;
MinX = minX;
MaxX = maxX;
DataX = DataGen.Range(minX, maxX + 1); DataX = DataGen.Range(minX, maxX + 1);
DataY = DataGen.Zeros(maxX - minX + 1); DataY = DataX.Select(i => (double)BillingData.GetCurveValueAt(data, i)).ToArray();
ParseGraphData(data, minX, maxX);
} }
public Graph(double[] dataX, double[] dataY) { private Graph(double[] dataX, double[] dataY, int precision, int minX, int maxX) {
Precision = precision;
MinX = minX;
MaxX = maxX;
DataX = dataX; DataX = dataX;
DataY = dataY; DataY = dataY;
} }
private void ParseGraphData(Dictionary<double, decimal> graphPoints, int minX, int maxX) { public double GetOechsleAt(int index) {
if (graphPoints.Keys.Count < 1) { return DataX[index];
return;
}
var minKey = graphPoints.Keys.Order().First();
var maxKey = graphPoints.Keys.OrderDescending().First();
if (!graphPoints.ContainsKey(minX)) {
graphPoints.Add(minX, graphPoints.GetValueOrDefault(minKey));
}
if (!graphPoints.ContainsKey(maxX)) {
graphPoints.Add(maxX, graphPoints.GetValueOrDefault(maxKey));
}
var keys = graphPoints.Keys.Order().ToArray();
for (int i = 0; i < keys.Length; i++) {
decimal point1Value = graphPoints[keys[i]];
if (i + 1 < keys.Length) {
decimal point2Value = graphPoints[keys[i + 1]];
if (point1Value == point2Value) {
for (int j = (int)(keys[i] - minX); j < keys[i + 1] - minX; j++) {
DataY[j] = (double)point1Value;
}
} else {
int steps = (int)Math.Abs(keys[i + 1] - keys[i]);
decimal step = (point2Value - point1Value) / steps;
DataY[(int)(keys[i] - minX)] = (double)point1Value;
DataY[(int)(keys[i + 1] - minX)] = (double)point2Value;
for (int j = (int)(keys[i] - minX); j < keys[i + 1] - minX - 1; j++) {
DataY[j + 1] = Math.Round(DataY[j] + (double)step, 4); // TODO richtig runden
}
}
}
else {
for (int j = (int)(keys[i] - minX); j < DataX.Length; j++) {
DataY[j] = (double)point1Value;
}
}
}
} }
public void FlattenGraph(int begin, int end, double value) { public void SetOechsleAt(int index, double oechsle) {
DataX[index] = oechsle;
}
public void SetPriceAt(int index, double price) {
DataY[index] = price;
}
public double GetPriceAt(int index) {
return DataY[index];
}
private void FlattenGraph(int begin, int end, double value) {
for (int i = begin; i <= end; i++) { for (int i = begin; i <= end; i++) {
DataY[i] = value; DataY[i] = value;
} }
} }
public void LinearIncreaseGraph(int begin, int end, double inc) { public void FlattenGraphLeft(int pointIndex) {
FlattenGraph(0, pointIndex, DataY[pointIndex]);
}
public void FlattenGraphRight(int pointIndex) {
FlattenGraph(pointIndex, DataY.Length - 1, DataY[pointIndex]);
}
private void LinearIncreaseGraph(int begin, int end, double inc) {
for (int i = begin; i < end; i++) { for (int i = begin; i < end; i++) {
DataY[i + 1] = DataY[i] + inc; DataY[i + 1] = Math.Round(DataY[i] + inc, Precision);
} }
} }
public JsonObject ToJson(string mode) { public void LinearIncreaseGraphToEnd(int begin, double inc) {
var data = new JsonObject(); LinearIncreaseGraph(begin, DataY.Length - 1, inc);
}
if (DataY[0] != DataY[1]) { public void InterpolateGraph(int firstPoint, int secondPoint) {
data.Add(new KeyValuePair<string, JsonNode?>(DataX[0] + mode, Math.Round(DataY[0], 4))); int steps = Math.Abs(firstPoint - secondPoint);
if (firstPoint == -1 || secondPoint == -1 || steps < 2) {
return;
} }
for (int i = 1; i < DataX.Length - 1; i++) { var (lowIndex, highIndex) = firstPoint < secondPoint ? (firstPoint, secondPoint) : (secondPoint, firstPoint);
if (Math.Round(DataY[i] - DataY[i - 1], 10) != Math.Round(DataY[i + 1] - DataY[i], 10)) { double step = (DataY[highIndex] - DataY[lowIndex]) / steps;
data.Add(new KeyValuePair<string, JsonNode?>(DataX[i] + mode, Math.Round(DataY[i], 4)));
} for (int i = lowIndex; i < highIndex - 1; i++) {
DataY[i + 1] = Math.Round(DataY[i] + step, Precision);
} }
if (DataY[^1] != DataY[^2]) {
data.Add(new KeyValuePair<string, JsonNode?>(DataX[^1] + mode, Math.Round(DataY[^1], 4)));
}
return data;
} }
public object Clone() { public object Clone() {
return new Graph((double[])DataX.Clone(), (double[])DataY.Clone()); return new Graph((double[])DataX.Clone(), (double[])DataY.Clone(), Precision, MinX, MaxX);
} }
} }
} }
+43 -36
View File
@@ -1,70 +1,77 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json.Nodes; using System.Linq;
namespace Elwig.Helpers.Billing { namespace Elwig.Helpers.Billing {
public class GraphEntry { public class GraphEntry {
public int Id { get; set; } public int Id { get; set; }
private readonly int Precision;
public BillingData.CurveMode Mode { get; set; } public BillingData.CurveMode Mode { get; set; }
public bool Abgewertet { get; set; }
public Graph DataGraph { get; set; } public Graph DataGraph { get; set; }
public Graph? GebundenGraph { get; set; } public Graph? GebundenGraph { get; set; }
public decimal? GebundenFlatPrice { get; set; } public decimal? GebundenFlatBonus { get; set; }
public List<string> Contracts { get; set; } public List<ContractSelection> Contracts { get; set; }
public string ContractsStringSimple => Contracts.Any() ? string.Join(", ", Contracts.Select(c => c.Listing)) : "-";
public string ContractsString => Contracts.Any() ? string.Join("\n", Contracts.Select(c => c.FullName)) : "-";
private int MinX { get; set; } private int MinX { get; set; }
private int MinXGebunden { get; set; }
private int MaxX { get; set; } private int MaxX { get; set; }
public GraphEntry(int id, BillingData.CurveMode mode, int minX, int maxX) { public GraphEntry(int id, int precision, BillingData.CurveMode mode, int minX, int minXGebunden, int maxX) {
Id = id; Id = id;
Precision = precision;
Mode = mode; Mode = mode;
Abgewertet = false;
MinX = minX; MinX = minX;
MinXGebunden = minXGebunden;
MaxX = maxX; MaxX = maxX;
DataGraph = new Graph(minX, maxX); DataGraph = new Graph(precision, minX, maxX);
Contracts = []; Contracts = [];
} }
public GraphEntry(int id, BillingData.CurveMode mode, Dictionary<double, decimal> data, int minX, int maxX) : public GraphEntry(int id, int precision, BillingData.CurveMode mode, Dictionary<double, decimal> data, Dictionary<double, decimal>? gebunden,
this(id, mode, minX, maxX) { int minX, int minXGebunden, int maxX) : this(id, precision, mode, minX, minXGebunden, maxX) {
DataGraph = new Graph(data, minX, maxX); DataGraph = new Graph(data, precision, minX, maxX);
if (gebunden != null) GebundenGraph = new Graph(gebunden, precision, minXGebunden, maxX);
} }
public GraphEntry(int id, BillingData.Curve curve, int minX, int maxX) : public GraphEntry(int id, int precision, BillingData.Curve curve, List<ContractSelection> contracts, int minX, int minXGebunden, int maxX) :
this(id, curve.Mode, minX, maxX) { this(id, precision, curve.Mode, minX, minXGebunden, maxX) {
DataGraph = new Graph(curve.Normal, minX, maxX); DataGraph = new Graph(curve.Normal, precision, minX, maxX);
if (curve.Gebunden != null) if (curve.Gebunden != null)
GebundenGraph = new Graph(curve.Gebunden, minX, maxX); GebundenGraph = new Graph(curve.Gebunden, precision, minXGebunden, maxX);
}
private GraphEntry(int id, BillingData.CurveMode mode, Graph dataGraph, Graph? gebundenGraph,
decimal? gebundenFlatPrice, List<string> contracts, int minX, int maxX) {
Id = id;
Mode = mode;
MinX = minX;
MaxX = maxX;
DataGraph = dataGraph;
GebundenGraph = gebundenGraph;
GebundenFlatPrice = gebundenFlatPrice;
Contracts = contracts; Contracts = contracts;
} }
public JsonObject ToJson() { private GraphEntry(int id, int precision, BillingData.CurveMode mode, Graph dataGraph, Graph? gebundenGraph,
var curve = new JsonObject { decimal? gebundenFlatPrice, List<ContractSelection> contracts, int minX, int minXGebunden, int maxX) {
["id"] = Id, Id = id;
["mode"] = Mode.ToString().ToLower(), Precision = precision;
}; Mode = mode;
MinX = minX;
MinXGebunden = minXGebunden;
MaxX = maxX;
DataGraph = dataGraph;
GebundenGraph = gebundenGraph;
GebundenFlatBonus = gebundenFlatPrice;
Contracts = contracts;
}
curve["data"] = DataGraph.ToJson(Mode.ToString().ToLower()); public void AddGebundenGraph() {
GebundenGraph ??= new Graph(Precision, MinXGebunden, MaxX);
}
if (GebundenFlatPrice != null) { public void RemoveGebundenGraph() {
curve["geb"] = GebundenFlatPrice.ToString(); GebundenGraph = null;
} else if (GebundenGraph != null) { }
curve["geb"] = GebundenGraph.ToJson(Mode.ToString().ToLower());
}
return curve; public void SetGebundenFlatBonus(decimal? value) {
GebundenFlatBonus = value;
} }
public GraphEntry Copy(int id) { public GraphEntry Copy(int id) {
return new GraphEntry(id, Mode, (Graph)DataGraph.Clone(), (Graph?)GebundenGraph?.Clone(), GebundenFlatPrice, Contracts, MinX, MaxX); return new GraphEntry(id, Precision, Mode, (Graph)DataGraph.Clone(), (Graph?)GebundenGraph?.Clone(), GebundenFlatBonus, [], MinX, MinXGebunden, MaxX);
} }
} }
} }
+5 -64
View File
@@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.Linq; using System.Linq;
using System.Text.Json.Nodes; using System.Text.Json.Nodes;
@@ -26,45 +25,12 @@ namespace Elwig.Helpers.Billing {
return new(ParseJson(json), attributeVariants); return new(ParseJson(json), attributeVariants);
} }
private Dictionary<string, Curve> GetData(JsonObject data) { private Dictionary<string, Curve> GetData(JsonNode data) {
Dictionary<string, Curve> dict; return GetSelection(data, AttributeVariants).ToDictionary(e => e.Key, e => LookupCurve(e.Value));
if (data["default"] is JsonValue def) {
var c = LookupCurve(def);
dict = AttributeVariants.ToDictionary(e => e, _ => c);
} else {
dict = [];
}
var variants = data.Where(p => !p.Key.StartsWith('/') && p.Key.Length == 2);
var attributes = data.Where(p => p.Key.StartsWith('/'));
var others = data.Where(p => !p.Key.StartsWith('/') && p.Key.Length > 2);
foreach (var (idx, v) in variants) {
var curve = LookupCurve(v?.AsValue() ?? throw new InvalidOperationException());
foreach (var i in AttributeVariants.Where(e => e.StartsWith(idx[..^1]))) {
dict[i] = curve;
}
}
foreach (var (idx, v) in attributes) {
var curve = LookupCurve(v?.AsValue() ?? throw new InvalidOperationException());
foreach (var i in AttributeVariants.Where(e => e[2..] == idx[1..])) {
dict[i] = curve;
}
}
foreach (var (idx, v) in others) {
var curve = LookupCurve(v?.AsValue() ?? throw new InvalidOperationException());
dict[idx.Replace("/", "")] = curve;
}
return dict;
} }
protected Dictionary<string, Curve> GetPaymentData() { protected Dictionary<string, Curve> GetPaymentData() {
var p = GetPaymentEntry(); return GetData(GetPaymentEntry());
if (p is JsonValue val) {
var c = LookupCurve(val);
return AttributeVariants.ToDictionary(e => e, _ => c);
}
return GetData(p?.AsObject() ?? throw new InvalidOperationException());
} }
protected Dictionary<string, Curve> GetQualityData() { protected Dictionary<string, Curve> GetQualityData() {
@@ -73,14 +39,7 @@ namespace Elwig.Helpers.Billing {
if (q == null) return dict; if (q == null) return dict;
foreach (var (qualid, data) in q) { foreach (var (qualid, data) in q) {
Dictionary<string, Curve> qualDict; foreach (var (idx, d) in GetData(data ?? throw new InvalidOperationException())) {
if (data is JsonValue val) {
var c = LookupCurve(val);
qualDict = AttributeVariants.ToDictionary(e => e, _ => c);
} else {
qualDict = GetData(data?.AsObject() ?? throw new InvalidOperationException());
}
foreach (var (idx, d) in qualDict) {
dict[$"{qualid}/{idx}"] = d; dict[$"{qualid}/{idx}"] = d;
} }
} }
@@ -90,25 +49,7 @@ namespace Elwig.Helpers.Billing {
public decimal CalculatePrice(string sortid, string? attrid, string qualid, bool gebunden, double oe, double kmw) { public decimal CalculatePrice(string sortid, string? attrid, string qualid, bool gebunden, double oe, double kmw) {
var curve = GetQualityCurve(qualid, sortid, attrid) ?? GetCurve(sortid, attrid); var curve = GetQualityCurve(qualid, sortid, attrid) ?? GetCurve(sortid, attrid);
var d = (gebunden ? curve.Gebunden : null) ?? curve.Normal; return GetCurveValueAt((gebunden ? curve.Gebunden : null) ?? curve.Normal, curve.Mode == CurveMode.Oe ? oe : kmw);
if (d.Count == 1) return d.First().Value;
var r = curve.Mode == CurveMode.Oe ? oe : kmw;
var lt = d.Keys.Where(v => v <= r);
var gt = d.Keys.Where(v => v >= r);
if (!lt.Any()) {
return d[gt.Min()];
} else if (!gt.Any()) {
return d[lt.Max()];
}
var max = lt.Max();
var min = gt.Min();
if (max == min) return d[r];
var p1 = ((decimal)r - (decimal)min) / ((decimal)max - (decimal)min);
var p2 = 1 - p1;
return d[min] * p2 + d[max] * p1;
} }
private Curve LookupCurve(JsonValue val) { private Curve LookupCurve(JsonValue val) {
+14 -1
View File
@@ -68,19 +68,32 @@ namespace Elwig.Models.Entities {
[InverseProperty("Delivery")] [InverseProperty("Delivery")]
public virtual ISet<DeliveryPart> Parts { get; private set; } public virtual ISet<DeliveryPart> Parts { get; private set; }
[NotMapped]
public IEnumerable<DeliveryPart> FilteredParts => PartFilter == null ? Parts : Parts.Where(p => PartFilter(p));
[NotMapped]
public Predicate<DeliveryPart>? PartFilter { get; set; }
public int Weight => Parts.Select(p => p.Weight).Sum(); public int Weight => Parts.Select(p => p.Weight).Sum();
public int FilteredWeight => FilteredParts.Select(p => p.Weight).Sum();
public IEnumerable<string> SortIds => Parts public IEnumerable<string> SortIds => Parts
.GroupBy(p => p.SortId) .GroupBy(p => p.SortId)
.OrderByDescending(g => g.Select(p => p.Weight).Sum()) .OrderByDescending(g => g.Select(p => p.Weight).Sum())
.Select(g => g.Select(p => p.SortId).First()); .Select(g => g.Key);
public IEnumerable<string> FilteredSortIds => FilteredParts
.GroupBy(p => p.SortId)
.OrderByDescending(g => g.Select(p => p.Weight).Sum())
.Select(g => g.Key);
public string SortIdString => string.Join(", ", SortIds); public string SortIdString => string.Join(", ", SortIds);
public string FilteredSortIdString => string.Join(", ", FilteredSortIds);
public double Kmw => Utils.AggregateDeliveryPartsKmw(Parts); public double Kmw => Utils.AggregateDeliveryPartsKmw(Parts);
public double FilteredKmw => Utils.AggregateDeliveryPartsKmw(FilteredParts);
public double Oe => Utils.KmwToOe(Kmw); public double Oe => Utils.KmwToOe(Kmw);
public double FilteredOe => Utils.KmwToOe(FilteredKmw);
public int SearchScore(IEnumerable<string> keywords) { public int SearchScore(IEnumerable<string> keywords) {
var list = new string?[] { var list = new string?[] {
+32 -27
View File
@@ -5,6 +5,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Elwig.Windows" xmlns:local="clr-namespace:Elwig.Windows"
xmlns:ctrl="clr-namespace:Elwig.Controls"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:ScottPlot="clr-namespace:ScottPlot;assembly=ScottPlot.WPF" xmlns:ScottPlot="clr-namespace:ScottPlot;assembly=ScottPlot.WPF"
mc:Ignorable="d" mc:Ignorable="d"
@@ -52,35 +53,36 @@
<ColumnDefinition Width="200"/> <ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Grid Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3"> <Grid Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="3">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/> <ColumnDefinition Width="560"/>
<ColumnDefinition Width="500"/> <ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Label Content="Graph:" Margin="10,0,0,0" FontSize="14" Grid.Column="0" VerticalAlignment="Center"/> <Label Content="Für:" Margin="10,0,0,0" FontSize="14" Grid.Column="0" VerticalAlignment="Center"/>
<TextBlock x:Name="GraphNum" Margin="0,0,40,0" FontSize="14" Width="50" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right"/> <xctk:CheckComboBox x:Name="ContractInput" Margin="50,0,0,0" Grid.Column="0"
Delimiter=", " AllItemsSelectedContent="Alle" IsEnabled="False" ItemSelectionChanged="ContractInput_Changed"
<Label Content="Für:" Margin="10,0,0,0" FontSize="14" Grid.Column="1" VerticalAlignment="Center"/> Width="500" Height="25" HorizontalAlignment="Left">
<xctk:CheckComboBox x:Name="AppliedInput" Margin="0,10,10,10" Grid.Column="1" <xctk:CheckComboBox.ItemTemplate>
Delimiter=", " AllItemsSelectedContent="Alle"
Width="400" HorizontalAlignment="Right">
<!--<xctk:CheckComboBox.ItemTemplate>
<DataTemplate> <DataTemplate>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock Text="{}" Width="40"/> <TextBlock Text="{Binding Variety.Name}" Width="150"/>
<TextBlock Text="{Binding Attribute.Name}"/>
</StackPanel> </StackPanel>
</DataTemplate> </DataTemplate>
</xctk:CheckComboBox.ItemTemplate>--> </xctk:CheckComboBox.ItemTemplate>
</xctk:CheckComboBox> </xctk:CheckComboBox>
<CheckBox x:Name="AbgewertetInput" Content="Abgewertet" IsEnabled="False" Checked="AbgewertetInput_Changed"
VerticalAlignment="Center" HorizontalAlignment="Left" Margin="0,0,0,0" Grid.Column="1"/>
</Grid> </Grid>
<ListBox x:Name="GraphList" Margin="10,10,35,50" Grid.Column="0" Grid.Row="1" SelectionChanged="GraphList_SelectionChanged"> <ListBox x:Name="GraphList" Margin="10,10,35,50" Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" SelectionChanged="GraphList_SelectionChanged">
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
<DataTemplate> <DataTemplate>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Id}" Width="40"/> <TextBlock Text="{Binding Id}" Width="30"/>
<TextBlock Text="{Binding Contracts}" Width="100"/> <TextBlock Text="{Binding ContractsStringSimple}" Width="140" ToolTip="{Binding ContractsString}"/>
</StackPanel> </StackPanel>
</DataTemplate> </DataTemplate>
</ListBox.ItemTemplate> </ListBox.ItemTemplate>
@@ -91,13 +93,13 @@
Click="SaveButton_Click"/> Click="SaveButton_Click"/>
<Button x:Name="AddButton" Content="&#xF8AA;" FontFamily="Segoe MDL2 Assets" FontSize="11" Padding="0,1.5,0,0" ToolTip="Neue Auszahlungsvariante hinzufügen" <Button x:Name="AddButton" Content="&#xF8AA;" FontFamily="Segoe MDL2 Assets" FontSize="11" Padding="0,1.5,0,0" ToolTip="Neue Auszahlungsvariante hinzufügen"
VerticalAlignment="Center" HorizontalAlignment="Right" Width="25" Height="25" Margin="5,0,5,60" Grid.Column="0" Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Right" Width="25" Height="25" Margin="5,0,5,60" Grid.Column="0" Grid.RowSpan="2" Grid.Row="0"
Click="AddButton_Click"/> Click="AddButton_Click"/>
<Button x:Name="CopyButton" Content="&#xE8C8;" FontFamily="Segoe MDL2 Assets" FontSize="12" Padding="0,0,0,0" IsEnabled="False" ToolTip="Ausgewählte Auszahlungsvariante duplizieren" <Button x:Name="CopyButton" Content="&#xE8C8;" FontFamily="Segoe MDL2 Assets" FontSize="12" Padding="0,0,0,0" IsEnabled="False" ToolTip="Ausgewählte Auszahlungsvariante duplizieren"
VerticalAlignment="Center" HorizontalAlignment="Right" Width="25" Height="25" Margin="0,0,5,0" Grid.Column="0" Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Right" Width="25" Height="25" Margin="0,0,5,0" Grid.Column="0" Grid.RowSpan="2" Grid.Row="0"
Click="CopyButton_Click"/> Click="CopyButton_Click"/>
<Button x:Name="DeleteButton" Content="&#xF8AB;" FontFamily="Segoe MDL2 Assets" FontSize="11" Padding="0,1.5,0,0" IsEnabled="False" ToolTip="Ausgewählte Auszahlungsvariante löschen" <Button x:Name="DeleteButton" Content="&#xF8AB;" FontFamily="Segoe MDL2 Assets" FontSize="11" Padding="0,1.5,0,0" IsEnabled="False" ToolTip="Ausgewählte Auszahlungsvariante löschen"
VerticalAlignment="Center" HorizontalAlignment="Right" Width="25" Height="25" Margin="5,60,5,0" Grid.Column="0" Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Right" Width="25" Height="25" Margin="5,60,5,0" Grid.Column="0" Grid.RowSpan="2" Grid.Row="0"
Click="DeleteButton_Click"/> Click="DeleteButton_Click"/>
<Grid Grid.Row="1" Grid.Column="1"> <Grid Grid.Row="1" Grid.Column="1">
@@ -121,11 +123,13 @@
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Label Content="Oechsle:" Margin="10,10,0,0" Grid.Column="0"/> <Label Content="Oechsle:" Margin="10,10,0,0" Grid.Column="0"/>
<TextBox x:Name="OechsleInput" Grid.Column="1" HorizontalAlignment="Left" Margin="0,10,0,0" Text="" Width="90" TextChanged="OechsleInput_TextChanged" LostFocus="OechsleInput_LostFocus"/> <ctrl:UnitTextBox x:Name="OechsleInput" Unit="°Oe" TextChanged="OechsleInput_TextChanged" IsEnabled="False" LostFocus="OechsleInput_LostFocus"
Grid.Column="1" Width="90" Margin="0,10,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Label Content="Preis pro kg:" Margin="10,40,0,0" Grid.Column="0"/>
<TextBox x:Name="PriceInput" Grid.Column="1" HorizontalAlignment="Left" Margin="0,40,0,0" Text="" Width="90" TextChanged="PriceInput_TextChanged" LostFocus="PriceInput_LostFocus"/>
<Label Content="Preis:" Margin="10,40,0,0" Grid.Column="0"/>
<ctrl:UnitTextBox x:Name="PriceInput" Unit="€/kg" TextChanged="PriceInput_TextChanged" IsEnabled="False" LostFocus="PriceInput_LostFocus"
Grid.Column="1" Width="90" Margin="0,40,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
</Grid> </Grid>
</GroupBox> </GroupBox>
@@ -137,13 +141,14 @@
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<StackPanel Margin="10,10,0,0"> <StackPanel Margin="10,10,0,0">
<RadioButton GroupName="GebundenType">Fix</RadioButton> <RadioButton x:Name="GebundenTypeFixed" GroupName="GebundenType" Checked="GebundenType_Checked" IsEnabled="False">Fix</RadioButton>
<RadioButton GroupName="GebundenType">Graph</RadioButton> <RadioButton x:Name="GebundenTypeGraph" GroupName="GebundenType" Checked="GebundenType_Checked" IsEnabled="False">Graph</RadioButton>
<RadioButton GroupName="GebundenType" IsChecked="True">Nein</RadioButton> <RadioButton x:Name="GebundenTypeNone" GroupName="GebundenType" Checked="GebundenType_Checked" IsEnabled="False">Nein</RadioButton>
</StackPanel> </StackPanel>
<TextBox x:Name="GebundenBonus" IsReadOnly="True" Grid.Column="1" HorizontalAlignment="Left" Margin="0,12,0,0" Text="" Width="90" TextChanged="GebundenBonus_TextChanged"/> <ctrl:UnitTextBox x:Name="GebundenFlatBonus" Unit="€/kg" TextChanged="GebundenFlatBonus_TextChanged" IsEnabled="False"
</Grid> Width="90" Margin="0,5,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Column="1"/>
</Grid>
</GroupBox> </GroupBox>
<GroupBox Header="Aktionen" Grid.Row="2" Margin="0,5,5,5"> <GroupBox Header="Aktionen" Grid.Row="2" Margin="0,5,5,5">
+322 -149
View File
@@ -2,12 +2,11 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using Elwig.Controls;
using Elwig.Helpers; using Elwig.Helpers;
using Elwig.Helpers.Billing; using Elwig.Helpers.Billing;
using Elwig.Models.Entities; using Elwig.Models.Entities;
@@ -15,28 +14,37 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.ChangeTracking;
using ScottPlot; using ScottPlot;
using ScottPlot.Plottable; using ScottPlot.Plottable;
using Xceed.Wpf.Toolkit.Primitives;
namespace Elwig.Windows { namespace Elwig.Windows {
public partial class ChartWindow : ContextWindow { public partial class ChartWindow : ContextWindow {
public static readonly Color ColorUngebunden = Color.Blue;
public static readonly Color ColorGebunden = Color.Gold;
public readonly int Year; public readonly int Year;
public readonly int AvNr; public readonly int AvNr;
private readonly PaymentVar PaymentVar; public Season Season;
private PaymentVar PaymentVar;
private ScatterPlot OechslePricePlotScatter; private ScatterPlot DataPlot;
private MarkerPlot HighlightedPoint; private ScatterPlot? GebundenPlot;
private MarkerPlot PrimaryMarkedPoint; private MarkerPlot HighlightedPointPlot;
private MarkerPlot SecondaryMarkedPoint; private MarkerPlot PrimaryMarkedPointPlot;
private Tooltip Tooltip; private MarkerPlot SecondaryMarkedPointPlot;
private Tooltip TooltipPlot;
private int LastHighlightedIndex = -1; private (Graph? graph, int index) LastHighlighted = (null, -1);
private int HighlightedIndex = -1; private (Graph? graph, int index) Highlighted = (null, -1);
private int PrimaryMarkedPointIndex = -1; private Graph? ActiveGraph = null;
private int SecondaryMarkedPointIndex = -1; private int PrimaryMarkedPoint = -1;
private int SecondaryMarkedPoint = -1;
private bool HoverChanged = false; private bool HoverChanged = false;
private bool HoverActive = false; private bool HoverActive = false;
private bool FillingInputs = false;
private const int MinOechsle = 50; private const int MinOechsle = 50;
private const int MinOechsleGebunden = 73;
private const int MaxOechsle = 140; private const int MaxOechsle = 140;
private List<GraphEntry> GraphEntries = []; private List<GraphEntry> GraphEntries = [];
@@ -46,6 +54,7 @@ namespace Elwig.Windows {
InitializeComponent(); InitializeComponent();
Year = year; Year = year;
AvNr = avnr; AvNr = avnr;
Season = Context.Seasons.Find(year) ?? throw new ArgumentException("Season not found");
PaymentVar = Context.PaymentVariants.Find(year, avnr) ?? throw new ArgumentException("PaymentVar not found"); PaymentVar = Context.PaymentVariants.Find(year, avnr) ?? throw new ArgumentException("PaymentVar not found");
Title = $"{PaymentVar?.Name} - Lese {year} - Elwig"; Title = $"{PaymentVar?.Name} - Lese {year} - Elwig";
} }
@@ -55,61 +64,80 @@ namespace Elwig.Windows {
} }
private async Task RefreshGraphList() { private async Task RefreshGraphList() {
await Context.PaymentVariants.LoadAsync(); PaymentVar = await Context.PaymentVariants.FindAsync(Year, AvNr) ?? throw new ArgumentException("PaymentVar not found");
await RefreshGraphListQuery(); Season = await Context.Seasons.FindAsync(Year) ?? throw new ArgumentException("Season not found");
}
private async Task RefreshGraphListQuery() { var attrVariants = (await Context.DeliveryParts
var attrVariants = Context.DeliveryParts
.Where(d => d.Year == Year) .Where(d => d.Year == Year)
.Select(d => $"{d.SortId}{d.AttrId}") .Select(d => $"{d.SortId}{d.AttrId}")
.Distinct() .Distinct()
.ToList() .ToListAsync())
.Union(Context.WineVarieties.Select(v => v.SortId)) .Union(Context.WineVarieties.Select(v => v.SortId))
.Order() .Order()
.ToList(); .ToList();
var data = EditBillingData.FromJson(PaymentVar.Data, attrVariants); var data = EditBillingData.FromJson(PaymentVar.Data, attrVariants);
GraphEntries.AddRange(data.GetPaymentGraphEntries()); GraphEntries = [ ..data.GetPaymentGraphEntries(Context, Season), ..data.GetQualityGraphEntries(Context, Season)];
GraphEntries.AddRange(data.GetQualityGraphEntries());
ControlUtils.RenewItemsSource(AppliedInput, attrVariants, g => g); var contracts = ContractSelection.GetContractsForYear(Context, Year);
ControlUtils.RenewItemsSource(GraphList, GraphEntries, g => (g as GraphEntry)?.Id, null, ControlUtils.RenewSourceDefault.IfOnly); FillingInputs = true;
ControlUtils.RenewItemsSource(ContractInput, contracts, g => (g as ContractSelection)?.Listing);
FillingInputs = false;
ControlUtils.RenewItemsSource(GraphList, GraphEntries, g => (g as GraphEntry)?.Id, GraphList_SelectionChanged, ControlUtils.RenewSourceDefault.First);
SelectedGraphEntry = GraphList.SelectedItem as GraphEntry;
RefreshInputs(); RefreshInputs();
} }
private string ParseContracts(JsonObject auszahlungsSorten, int num) { private void RefreshInputs() {
return "";
}
private void RefreshInputs(bool validate = false) {
ResetPlot(); ResetPlot();
if (!PaymentVar.TestVariant) { if (SelectedGraphEntry != null) {
AddButton.IsEnabled = false;
CopyButton.IsEnabled = false;
DeleteButton.IsEnabled = false;
OechsleInput.IsReadOnly = true;
PriceInput.IsReadOnly = true;
} else if (SelectedGraphEntry != null) {
CopyButton.IsEnabled = true; CopyButton.IsEnabled = true;
DeleteButton.IsEnabled = true; DeleteButton.IsEnabled = true;
OechsleInput.IsReadOnly = false; //EnableUnitTextBox(OechsleInput);
GebundenTypeFixed.IsEnabled = true;
GebundenTypeGraph.IsEnabled = true;
GebundenTypeNone.IsEnabled = true;
ContractInput.IsEnabled = true;
AbgewertetInput.IsEnabled = true;
EnableOptionButtons(); EnableOptionButtons();
FillInputs(); FillInputs();
} else { } else {
CopyButton.IsEnabled = false; CopyButton.IsEnabled = false;
DeleteButton.IsEnabled = false; DeleteButton.IsEnabled = false;
OechsleInput.IsReadOnly = true; DisableUnitTextBox(OechsleInput);
DisableOptionButtons(); DisableOptionButtons();
} }
if (!PaymentVar.TestVariant) {
AddButton.IsEnabled = false;
CopyButton.IsEnabled = false;
DeleteButton.IsEnabled = false;
DisableUnitTextBox(OechsleInput);
DisableUnitTextBox(PriceInput);
GebundenTypeFixed.IsEnabled = false;
GebundenTypeGraph.IsEnabled = false;
GebundenTypeNone.IsEnabled = false;
ContractInput.IsEnabled = false;
AbgewertetInput.IsEnabled = false;
}
GC.Collect(); GC.Collect();
} }
private void FillInputs() { private void FillInputs() {
GraphNum.Text = SelectedGraphEntry.Id.ToString(); FillingInputs = true;
if (SelectedGraphEntry?.GebundenFlatBonus != null) {
GebundenTypeFixed.IsChecked = true;
} else if (SelectedGraphEntry?.GebundenGraph != null) {
GebundenTypeGraph.IsChecked = true;
} else {
GebundenTypeNone.IsChecked = true;
}
ControlUtils.SelectCheckComboBoxItems(ContractInput, SelectedGraphEntry?.Contracts ?? [], i => (i as ContractSelection)?.Listing);
InitPlot(); InitPlot();
OechslePricePlot.IsEnabled = true; OechslePricePlot.IsEnabled = true;
FillingInputs = false;
} }
protected override async Task OnRenewContext() { protected override async Task OnRenewContext() {
@@ -117,39 +145,50 @@ namespace Elwig.Windows {
} }
private void InitPlot() { private void InitPlot() {
OechslePricePlotScatter = OechslePricePlot.Plot.AddScatter(SelectedGraphEntry.DataGraph.DataX, SelectedGraphEntry.DataGraph.DataY); if (SelectedGraphEntry?.GebundenGraph != null) {
GebundenPlot = OechslePricePlot.Plot.AddScatter(SelectedGraphEntry.GebundenGraph.DataX, SelectedGraphEntry.GebundenGraph.DataY, label: "Gebunden");
GebundenPlot.LineColor = ColorGebunden;
GebundenPlot.MarkerColor = ColorGebunden;
GebundenPlot.MarkerSize = 9;
}
DataPlot = OechslePricePlot.Plot.AddScatter(SelectedGraphEntry!.DataGraph.DataX, SelectedGraphEntry!.DataGraph.DataY, label: "Ungebunden");
DataPlot.LineColor = ColorUngebunden;
DataPlot.MarkerColor = ColorUngebunden;
DataPlot.MarkerSize = 9;
if (SelectedGraphEntry?.GebundenGraph == null) {
ChangeActiveGraph(SelectedGraphEntry?.DataGraph);
}
OechslePricePlot.RightClicked -= OechslePricePlot.DefaultRightClickEvent;
OechslePricePlot.Configuration.DoubleClickBenchmark = false; OechslePricePlot.Configuration.DoubleClickBenchmark = false;
OechslePricePlotScatter.LineColor = Color.Blue;
OechslePricePlotScatter.MarkerColor = Color.Blue;
OechslePricePlotScatter.MarkerSize = 9;
//OechslePricePlot.Plot.XAxis.ManualTickSpacing(1); //OechslePricePlot.Plot.XAxis.ManualTickSpacing(1);
OechslePricePlot.Plot.YAxis.ManualTickSpacing(0.1); OechslePricePlot.Plot.YAxis.ManualTickSpacing(0.1);
OechslePricePlot.Plot.SetAxisLimits(MinOechsle - 1, MaxOechsle + 1, -0.1, 2); OechslePricePlot.Plot.SetAxisLimits(Math.Min(MinOechsle, MinOechsleGebunden) - 1, MaxOechsle + 1, -0.1, 2);
OechslePricePlot.Plot.Layout(padding: 0); OechslePricePlot.Plot.Layout(padding: 0);
OechslePricePlot.Plot.XAxis2.Layout(padding: 0); OechslePricePlot.Plot.XAxis2.Layout(padding: 0);
OechslePricePlot.Plot.YAxis.Layout(padding: 0); OechslePricePlot.Plot.YAxis.Layout(padding: 0);
OechslePricePlot.Plot.YAxis2.Layout(padding: 0); OechslePricePlot.Plot.YAxis2.Layout(padding: 0);
HighlightedPoint = OechslePricePlot.Plot.AddPoint(0, 0); HighlightedPointPlot = OechslePricePlot.Plot.AddPoint(0, 0);
HighlightedPoint.Color = Color.Red; HighlightedPointPlot.Color = Color.Red;
HighlightedPoint.MarkerSize = 10; HighlightedPointPlot.MarkerSize = 10;
HighlightedPoint.MarkerShape = MarkerShape.openCircle; HighlightedPointPlot.MarkerShape = MarkerShape.openCircle;
HighlightedPoint.IsVisible = false; HighlightedPointPlot.IsVisible = false;
PrimaryMarkedPoint = OechslePricePlot.Plot.AddPoint(0, 0); PrimaryMarkedPointPlot = OechslePricePlot.Plot.AddPoint(0, 0);
PrimaryMarkedPoint.Color = Color.Red; PrimaryMarkedPointPlot.Color = Color.Red;
PrimaryMarkedPoint.MarkerSize = 6; PrimaryMarkedPointPlot.MarkerSize = 6;
PrimaryMarkedPoint.MarkerShape = MarkerShape.filledCircle; PrimaryMarkedPointPlot.MarkerShape = MarkerShape.filledCircle;
PrimaryMarkedPoint.IsVisible = false; PrimaryMarkedPointPlot.IsVisible = false;
SecondaryMarkedPoint = OechslePricePlot.Plot.AddPoint(0, 0); SecondaryMarkedPointPlot = OechslePricePlot.Plot.AddPoint(0, 0);
SecondaryMarkedPoint.Color = Color.Red; SecondaryMarkedPointPlot.Color = Color.Red;
SecondaryMarkedPoint.MarkerSize = 6; SecondaryMarkedPointPlot.MarkerSize = 6;
SecondaryMarkedPoint.MarkerShape = MarkerShape.filledCircle; SecondaryMarkedPointPlot.MarkerShape = MarkerShape.filledCircle;
SecondaryMarkedPoint.IsVisible = false; SecondaryMarkedPointPlot.IsVisible = false;
OechslePricePlot.Refresh(); OechslePricePlot.Refresh();
@@ -158,8 +197,12 @@ namespace Elwig.Windows {
} }
private void ResetPlot() { private void ResetPlot() {
PrimaryMarkedPointIndex = -1; PrimaryMarkedPoint = -1;
OechslePricePlot.Plot.Remove(OechslePricePlotScatter); SecondaryMarkedPoint = -1;
ChangeActiveGraph(null);
HideGradationLines();
OechslePricePlot.Plot.Remove(DataPlot);
OechslePricePlot.Plot.Remove(GebundenPlot);
OechslePricePlot.Plot.Clear(); OechslePricePlot.Plot.Clear();
OechslePricePlot.Reset(); OechslePricePlot.Reset();
OechslePricePlot.Refresh(); OechslePricePlot.Refresh();
@@ -171,20 +214,16 @@ namespace Elwig.Windows {
point.IsVisible = visible; point.IsVisible = visible;
} }
private void FlattenGraph(int begin, int end, double value) {
SelectedGraphEntry.DataGraph.FlattenGraph(begin, end, value);
OechslePricePlot.Render();
}
private void LinearIncreaseGraph(int begin, int end, double inc) { private void LinearIncreaseGraph(int begin, int end, double inc) {
SelectedGraphEntry.DataGraph.LinearIncreaseGraph(begin, end, inc);
OechslePricePlot.Render();
} }
private void EnableActionButtons() { private void EnableActionButtons() {
LeftFlatButton.IsEnabled = true; if (PaymentVar.TestVariant) {
RightFlatButton.IsEnabled = true; LeftFlatButton.IsEnabled = true;
LinearIncreaseButton.IsEnabled = true; RightFlatButton.IsEnabled = true;
LinearIncreaseButton.IsEnabled = true;
}
} }
private void DisableActionButtons() { private void DisableActionButtons() {
@@ -239,10 +278,10 @@ namespace Elwig.Windows {
} }
private void RefreshGradationLines() { private void RefreshGradationLines() {
if (GradationLinesInput.IsChecked == true) { if (GradationLinesInput.IsChecked == true && SelectedGraphEntry != null && !OechslePricePlot.Plot.GetPlottables().OfType<VLine>().Any()) {
ShowGradationLines(); ShowGradationLines();
ShowLegend(); ShowLegend();
} else { } else if (GradationLinesInput.IsChecked == false) {
HideGradationLines(); HideGradationLines();
HideLegend(); HideLegend();
} }
@@ -250,9 +289,9 @@ namespace Elwig.Windows {
} }
private void ShowGradationLines() { private void ShowGradationLines() {
OechslePricePlot.Plot.AddVerticalLine(68, Color.Red, 2, label: "68 Oechsle (LDW)"); OechslePricePlot.Plot.AddVerticalLine(68, Color.Red, 2, label: "68 °Oe (LDW)");
OechslePricePlot.Plot.AddVerticalLine(73, Color.Orange, 2, label: "73 Oechsle (QUW)"); OechslePricePlot.Plot.AddVerticalLine(73, Color.Orange, 2, label: "73 °Oe (QUW)");
OechslePricePlot.Plot.AddVerticalLine(84, Color.Green, 2, label: "84 Oechsle (KAB)"); OechslePricePlot.Plot.AddVerticalLine(84, Color.Green, 2, label: "84 °Oe (KAB)");
} }
private void HideGradationLines() { private void HideGradationLines() {
@@ -260,90 +299,93 @@ namespace Elwig.Windows {
} }
private void ShowLegend() { private void ShowLegend() {
OechslePricePlot.Plot.Legend(true, Alignment.UpperRight); OechslePricePlot.Plot.Legend(true, Alignment.UpperLeft);
} }
private void HideLegend() { private void HideLegend() {
OechslePricePlot.Plot.Legend(false, Alignment.UpperRight); OechslePricePlot.Plot.Legend(false, Alignment.UpperLeft);
} }
private void OechsleInput_TextChanged(object sender, TextChangedEventArgs evt) { private void OechsleInput_TextChanged(object sender, TextChangedEventArgs evt) {
if (ActiveGraph == null || SelectedGraphEntry == null) {
return;
}
bool success = int.TryParse(OechsleInput.Text, out int oechsle); bool success = int.TryParse(OechsleInput.Text, out int oechsle);
SecondaryMarkedPointIndex = -1; SecondaryMarkedPoint = -1;
ChangeMarker(SecondaryMarkedPoint, false); ChangeMarker(SecondaryMarkedPointPlot, false);
if (success) { if (success) {
if (oechsle >= MinOechsle && oechsle <= MaxOechsle) { if (oechsle >= ActiveGraph.MinX && oechsle <= ActiveGraph.MaxX) {
PrimaryMarkedPointIndex = oechsle - MinOechsle; PrimaryMarkedPoint = oechsle - ActiveGraph.MinX;
ChangeMarker(PrimaryMarkedPoint, true, SelectedGraphEntry.DataGraph.DataX[PrimaryMarkedPointIndex], SelectedGraphEntry.DataGraph.DataY[PrimaryMarkedPointIndex]); ChangeMarker(PrimaryMarkedPointPlot, true, ActiveGraph.GetOechsleAt(PrimaryMarkedPoint), ActiveGraph.GetPriceAt(PrimaryMarkedPoint));
PriceInput.Text = SelectedGraphEntry.DataGraph.DataY[PrimaryMarkedPointIndex].ToString(); PriceInput.Text = ActiveGraph.GetPriceAt(PrimaryMarkedPoint).ToString();
EnableActionButtons(); EnableActionButtons();
OechslePricePlot.Render(); OechslePricePlot.Render();
PriceInput.IsReadOnly = false; EnableUnitTextBox(PriceInput);
return; return;
} }
} }
PrimaryMarkedPointIndex = -1; PrimaryMarkedPoint = -1;
ChangeMarker(PrimaryMarkedPoint, false); //ChangeActiveGraph(null);
ChangeMarker(PrimaryMarkedPointPlot, false);
DisableActionButtons(); DisableActionButtons();
PriceInput.Text = ""; PriceInput.Text = "";
DisableUnitTextBox(PriceInput);
OechslePricePlot.Render(); OechslePricePlot.Render();
PriceInput.IsReadOnly = true; DisableUnitTextBox(PriceInput);
} }
private void PriceInput_TextChanged(object sender, RoutedEventArgs evt) { private void PriceInput_TextChanged(object sender, TextChangedEventArgs evt) {
if (PrimaryMarkedPointIndex != -1) { if (PrimaryMarkedPoint != -1 && ActiveGraph != null) {
bool success = Double.TryParse(PriceInput.Text, out double price); bool success = double.TryParse(PriceInput.Text, out double price);
if (success) { if (success) {
SelectedGraphEntry.DataGraph.DataY[PrimaryMarkedPointIndex] = price; ActiveGraph.SetPriceAt(PrimaryMarkedPoint, price);
PrimaryMarkedPoint.Y = price; PrimaryMarkedPointPlot.Y = price;
OechslePricePlot.Refresh(); OechslePricePlot.Refresh();
} }
} }
} }
private void LeftFlatButton_Click(object sender, RoutedEventArgs evt) { private void LeftFlatButton_Click(object sender, RoutedEventArgs evt) {
if (PrimaryMarkedPointIndex == -1) { if (PrimaryMarkedPoint == -1 || ActiveGraph == null) {
return; return;
} }
FlattenGraph(0, PrimaryMarkedPointIndex, SelectedGraphEntry.DataGraph.DataY[PrimaryMarkedPointIndex]); ActiveGraph.FlattenGraphLeft(PrimaryMarkedPoint);
OechslePricePlot.Render();
} }
private void RightFlatButton_Click(object sender, RoutedEventArgs evt) { private void RightFlatButton_Click(object sender, RoutedEventArgs evt) {
if (PrimaryMarkedPointIndex == -1) { if (PrimaryMarkedPoint == -1 || ActiveGraph == null) {
return; return;
} }
FlattenGraph(PrimaryMarkedPointIndex, SelectedGraphEntry.DataGraph.DataY.Length - 1, SelectedGraphEntry.DataGraph.DataY[PrimaryMarkedPointIndex]); ActiveGraph.FlattenGraphRight(PrimaryMarkedPoint);
OechslePricePlot.Render();
} }
private void InterpolateButton_Click(object sender, RoutedEventArgs evt) { private void InterpolateButton_Click(object sender, RoutedEventArgs evt) {
int steps = Math.Abs(PrimaryMarkedPointIndex - SecondaryMarkedPointIndex); if (PrimaryMarkedPoint == SecondaryMarkedPoint || PrimaryMarkedPoint == -1 || SecondaryMarkedPoint == -1 || ActiveGraph == null) {
if (PrimaryMarkedPointIndex == -1 || SecondaryMarkedPointIndex == -1 || steps < 2) {
return; return;
} }
var (lowIndex, highIndex) = PrimaryMarkedPointIndex < SecondaryMarkedPointIndex ? (PrimaryMarkedPointIndex, SecondaryMarkedPointIndex): (SecondaryMarkedPointIndex, PrimaryMarkedPointIndex); ActiveGraph.InterpolateGraph(PrimaryMarkedPoint, SecondaryMarkedPoint);
OechslePricePlot.Render();
double step = (SelectedGraphEntry.DataGraph.DataY[highIndex] - SelectedGraphEntry.DataGraph.DataY[lowIndex]) / steps;
for (int i = lowIndex; i < highIndex - 1; i++) {
SelectedGraphEntry.DataGraph.DataY[i + 1] = Math.Round(SelectedGraphEntry.DataGraph.DataY[i] + step, 4); // TODO richtig runden
}
} }
private void LinearIncreaseButton_Click(object sender, RoutedEventArgs e) { private void LinearIncreaseButton_Click(object sender, RoutedEventArgs e) {
if (PrimaryMarkedPointIndex == -1) { if (PrimaryMarkedPoint == -1 || ActiveGraph == null) {
return; return;
} }
double? priceIncrease = Utils.ShowLinearPriceIncreaseDialog(); double? priceIncrease = Utils.ShowLinearPriceIncreaseDialog();
if (priceIncrease == null) { if (priceIncrease == null) {
return; return;
} }
LinearIncreaseGraph(PrimaryMarkedPointIndex, SelectedGraphEntry.DataGraph.DataY.Length - 1, priceIncrease.Value); ActiveGraph.LinearIncreaseGraphToEnd(PrimaryMarkedPoint, priceIncrease.Value);
OechslePricePlot.Render();
} }
private void OechslePricePlot_MouseDown(object sender, MouseEventArgs e) { private void OechslePricePlot_MouseDown(object sender, MouseEventArgs e) {
@@ -353,83 +395,112 @@ namespace Elwig.Windows {
if (HoverActive) { if (HoverActive) {
if (PaymentVar.TestVariant && Keyboard.IsKeyDown(Key.LeftCtrl)) { if (PaymentVar.TestVariant && Keyboard.IsKeyDown(Key.LeftCtrl)) {
if (PrimaryMarkedPointIndex == -1) { if (PrimaryMarkedPoint == -1 || ActiveGraph == null || ActiveGraph != Highlighted.graph) {
return; return;
} }
SecondaryMarkedPointIndex = HighlightedIndex; SecondaryMarkedPoint = Highlighted.index;
ChangeMarker(SecondaryMarkedPoint, true, SelectedGraphEntry.DataGraph.DataX[SecondaryMarkedPointIndex], SelectedGraphEntry.DataGraph.DataY[SecondaryMarkedPointIndex]);
ChangeMarker(SecondaryMarkedPointPlot, true, ActiveGraph.GetOechsleAt(SecondaryMarkedPoint), ActiveGraph.GetPriceAt(SecondaryMarkedPoint));
InterpolateButton.IsEnabled = true; InterpolateButton.IsEnabled = true;
return; return;
} }
PrimaryMarkedPointIndex = HighlightedIndex; PrimaryMarkedPoint = Highlighted.index;
ChangeMarker(PrimaryMarkedPoint, true, SelectedGraphEntry.DataGraph.DataX[PrimaryMarkedPointIndex], SelectedGraphEntry.DataGraph.DataY[PrimaryMarkedPointIndex]); ChangeActiveGraph(Highlighted.graph);
OechsleInput.Text = SelectedGraphEntry.DataGraph.DataX[HighlightedIndex].ToString(); ChangeMarker(PrimaryMarkedPointPlot, true, ActiveGraph.GetOechsleAt(PrimaryMarkedPoint), ActiveGraph.GetPriceAt(PrimaryMarkedPoint));
PriceInput.Text = SelectedGraphEntry.DataGraph.DataY[HighlightedIndex].ToString();
if (PaymentVar.TestVariant) { OechsleInput.Text = Highlighted.graph.GetOechsleAt(Highlighted.index).ToString();
EnableActionButtons(); PriceInput.Text = Highlighted.graph.GetPriceAt(Highlighted.index).ToString();
}
EnableActionButtons();
} else { } else {
PrimaryMarkedPointIndex = -1; PrimaryMarkedPoint = -1;
SecondaryMarkedPointIndex = -1; SecondaryMarkedPoint = -1;
ChangeMarker(PrimaryMarkedPoint, false); if (SelectedGraphEntry!.GebundenGraph != null) {
ChangeMarker(SecondaryMarkedPoint, false); ChangeActiveGraph(null);
}
ChangeMarker(PrimaryMarkedPointPlot, false);
ChangeMarker(SecondaryMarkedPointPlot, false);
OechsleInput.Text = ""; OechsleInput.Text = "";
PriceInput.Text = ""; PriceInput.Text = "";
DisableUnitTextBox(PriceInput);
DisableActionButtons(); DisableActionButtons();
} }
} }
private (double, double, int)? MouseOnPlot(ScatterPlot? plot) {
if (plot == null) {
return null;
}
(double mouseCoordX, double mouseCoordY) = OechslePricePlot.GetMouseCoordinates();
(double mousePixelX, double mousePixelY) = OechslePricePlot.GetMousePixel();
double xyRatio = OechslePricePlot.Plot.XAxis.Dims.PxPerUnit / OechslePricePlot.Plot.YAxis.Dims.PxPerUnit;
(double pointX, double pointY, int pointIndex) = plot.GetPointNearest(mouseCoordX, mouseCoordY, xyRatio);
(double pointPixelX, double pointPixelY) = OechslePricePlot.Plot.GetPixel(pointX, pointY);
if (Math.Abs(mousePixelX - pointPixelX) < 3 && Math.Abs(mousePixelY - pointPixelY) < 3) {
return (pointX, pointY, pointIndex);
} else {
return null;
}
}
private void OechslePricePlot_MouseMove(object sender, MouseEventArgs e) { private void OechslePricePlot_MouseMove(object sender, MouseEventArgs e) {
if (GraphList.SelectedItem == null) { if (GraphList.SelectedItem == null) {
return; return;
} }
(double mouseCoordX, double mouseCoordY) = OechslePricePlot.GetMouseCoordinates(); (double x, double y, int index)? mouseOnData = MouseOnPlot(DataPlot);
double xyRatio = OechslePricePlot.Plot.XAxis.Dims.PxPerUnit / OechslePricePlot.Plot.YAxis.Dims.PxPerUnit; (double x, double y , int index)? mouseOnGebunden = MouseOnPlot(GebundenPlot);
(double pointX, double pointY, int pointIndex) = OechslePricePlotScatter.GetPointNearest(mouseCoordX, mouseCoordY, xyRatio);
(double mousePixelX, double mousePixelY) = OechslePricePlot.GetMousePixel(); Highlighted = LastHighlighted;
(double pointPixelX, double pointPixelY) = OechslePricePlot.Plot.GetPixel(pointX, pointY);
HighlightedIndex = LastHighlightedIndex; if (mouseOnData != null) {
ChangeMarker(HighlightedPointPlot, true, mouseOnData.Value.x, mouseOnData.Value.y);
if (Math.Abs(mousePixelX - pointPixelX) < 3 && Math.Abs(mousePixelY - pointPixelY) < 3) { HighlightedPointPlot.IsVisible = true;
ChangeMarker(HighlightedPoint, true, pointX, pointY);
HighlightedPoint.IsVisible = true;
HoverChanged = true ^ HoverActive; HoverChanged = true ^ HoverActive;
HoverActive = true; HoverActive = true;
HandleTooltip(mouseOnData.Value.x, mouseOnData.Value.y, mouseOnData.Value.index, SelectedGraphEntry!.DataGraph);
} else if (mouseOnGebunden != null) {
ChangeMarker(HighlightedPointPlot, true, mouseOnGebunden.Value.x, mouseOnGebunden.Value.y);
HighlightedPointPlot.IsVisible = true;
HoverChanged = true ^ HoverActive;
HoverActive = true;
HandleTooltip(mouseOnGebunden.Value.x, mouseOnGebunden.Value.y, mouseOnGebunden.Value.index, SelectedGraphEntry!.GebundenGraph!);
} else { } else {
ChangeMarker(HighlightedPoint, false); ChangeMarker(HighlightedPointPlot, false);
HoverChanged= false ^ HoverActive; HoverChanged = false ^ HoverActive;
HoverActive= false; HoverActive = false;
OechslePricePlot.Plot.Remove(Tooltip); OechslePricePlot.Plot.Remove(TooltipPlot);
OechslePricePlot.Render(); OechslePricePlot.Render();
} }
}
if (LastHighlightedIndex != HighlightedIndex || HoverChanged) { private void HandleTooltip(double pointX, double pointY, int pointIndex, Graph g) {
OechslePricePlot.Plot.Remove(Tooltip); if (LastHighlighted != Highlighted || HoverChanged) {
OechslePricePlot.Plot.Remove(TooltipPlot);
if (TooltipInput.IsChecked == true) { if (TooltipInput.IsChecked == true) {
Tooltip = OechslePricePlot.Plot.AddTooltip($"Oechsle: {pointX:N2}, Preis: {Math.Round(pointY, 4)})", pointX, pointY); TooltipPlot = OechslePricePlot.Plot.AddTooltip($"Oechsle: {pointX:N2}, Preis: {Math.Round(pointY, Season.Precision)}€/kg)", pointX, pointY);
} }
LastHighlightedIndex = pointIndex; LastHighlighted = (g, pointIndex);
HoverChanged = false; HoverChanged = false;
OechslePricePlot.Render(); OechslePricePlot.Render();
} }
} }
private int getMaxGraphId() { private int GetMaxGraphId() {
return GraphEntries.Count == 0 ? 0 : GraphEntries.Select(g => g.Id).Max(); return GraphEntries.Count == 0 ? 0 : GraphEntries.Select(g => g.Id).Max();
} }
private void AddButton_Click(object sender, RoutedEventArgs e) { private void AddButton_Click(object sender, RoutedEventArgs e) {
GraphEntry newGraphEntry = new(getMaxGraphId() + 1, BillingData.CurveMode.Oe, MinOechsle, MaxOechsle); GraphEntry newGraphEntry = new(GetMaxGraphId() + 1, Season.Precision, BillingData.CurveMode.Oe, MinOechsle, MinOechsleGebunden, MaxOechsle);
GraphEntries.Add(newGraphEntry); GraphEntries.Add(newGraphEntry);
GraphList.Items.Refresh(); GraphList.Items.Refresh();
GraphList.SelectedItem = newGraphEntry; GraphList.SelectedItem = newGraphEntry;
@@ -438,7 +509,7 @@ namespace Elwig.Windows {
private void CopyButton_Click(object sender, RoutedEventArgs e) { private void CopyButton_Click(object sender, RoutedEventArgs e) {
if (SelectedGraphEntry == null) return; if (SelectedGraphEntry == null) return;
GraphEntry newGraphEntry = SelectedGraphEntry.Copy(getMaxGraphId() + 1); GraphEntry newGraphEntry = SelectedGraphEntry.Copy(GetMaxGraphId() + 1);
GraphEntries.Add(newGraphEntry); GraphEntries.Add(newGraphEntry);
GraphList.Items.Refresh(); GraphList.Items.Refresh();
GraphList.SelectedItem = newGraphEntry; GraphList.SelectedItem = newGraphEntry;
@@ -457,16 +528,67 @@ namespace Elwig.Windows {
} }
} }
private void SaveButton_Click(object sender, RoutedEventArgs e) { private async void SaveButton_Click(object sender, RoutedEventArgs e) {
//TODO SAVE var origData = BillingData.FromJson(PaymentVar.Data);
var data = origData.FromGraphEntries(GraphEntries);
EntityEntry<PaymentVar>? tr = null;
try {
PaymentVar.Data = data.ToJsonString();
tr = Context.Update(PaymentVar);
await Context.SaveChangesAsync();
LockContext = false;
await App.HintContextChange();
} catch (Exception exc) {
if (tr != null) await tr.ReloadAsync();
var str = "Der Eintrag konnte nicht in der Datenbank gespeichert werden!\n\n" + exc.Message;
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
MessageBox.Show(str, "Auszahlungsvariante speichern", MessageBoxButton.OK, MessageBoxImage.Error);
}
LockContext = true;
}
private void EnableUnitTextBox(UnitTextBox u) {
if (PaymentVar.TestVariant) {
u.IsEnabled = true;
u.TextBox.IsReadOnly = false;
}
}
private void DisableUnitTextBox(UnitTextBox u) {
u.IsEnabled = false;
u.TextBox.IsReadOnly = true;
}
private void ChangeActiveGraph(Graph? g) {
if (g != null && g == SelectedGraphEntry?.DataGraph) {
EnableUnitTextBox(OechsleInput);
ChangeLineWidth(DataPlot, 4);
ChangeLineWidth(GebundenPlot, 1);
} else if (g != null && g == SelectedGraphEntry?.GebundenGraph) {
EnableUnitTextBox(OechsleInput);
ChangeLineWidth(GebundenPlot, 4);
ChangeLineWidth(DataPlot, 1);
} else {
DisableUnitTextBox(OechsleInput);
DisableUnitTextBox(PriceInput);
OechsleInput.Text = "";
PriceInput.Text = "";
ChangeLineWidth(DataPlot, 1);
ChangeLineWidth(GebundenPlot, 1);
}
ActiveGraph = g;
}
private void ChangeLineWidth(ScatterPlot? p, double lineWidth) {
if (p != null) {
p.LineWidth = lineWidth;
}
} }
private void GraphList_SelectionChanged(object sender, SelectionChangedEventArgs e) { private void GraphList_SelectionChanged(object sender, SelectionChangedEventArgs e) {
SelectedGraphEntry = (GraphEntry)GraphList.SelectedItem; SelectedGraphEntry = GraphList.SelectedItem as GraphEntry;
RefreshInputs(); RefreshInputs();
//var x = OechslePricePlot.Plot.GetPlottables().OfType<ScatterPlot>();
//MessageBox.Show($"SelectionChanged\nLength: {x.ToList().Count}, Ys: {string.Join(", ", ((ScatterPlot)x.First()).Ys)}");
} }
private void PriceInput_LostFocus(object sender, RoutedEventArgs e) { private void PriceInput_LostFocus(object sender, RoutedEventArgs e) {
@@ -477,8 +599,59 @@ namespace Elwig.Windows {
} }
private void GebundenBonus_TextChanged(object sender, TextChangedEventArgs evt) { private void GebundenFlatBonus_TextChanged(object sender, TextChangedEventArgs e) {
var r = Validator.CheckDecimal(GebundenFlatBonus.TextBox, true, 2, 8);
if (r.IsValid) {
SelectedGraphEntry?.SetGebundenFlatBonus(decimal.Parse(GebundenFlatBonus.Text));
}
}
private void ContractInput_Changed(object sender, ItemSelectionChangedEventArgs e) {
if (FillingInputs) return;
if (e.IsSelected == true) {
RemoveContractFromOtherGraphEntries(e.Item.ToString());
}
var r = ContractInput.SelectedItems.Cast<ContractSelection>();
SelectedGraphEntry!.Contracts = r.ToList();
GraphList.Items.Refresh();
}
private void RemoveContractFromOtherGraphEntries(string? contract) {
if (contract == null) return;
foreach (var ge in GraphEntries) {
if (ge != SelectedGraphEntry) {
ge.Contracts.RemoveAll(c => c.Listing.Equals(contract));
}
}
}
private void AbgewertetInput_Changed(object sender, RoutedEventArgs e) {
if (SelectedGraphEntry == null) return;
SelectedGraphEntry.Abgewertet = AbgewertetInput.IsChecked == true;
}
private void GebundenType_Checked(object sender, RoutedEventArgs e) {
if (FillingInputs) return;
if (SelectedGraphEntry == null) {
DisableUnitTextBox(GebundenFlatBonus);
return;
} else if (GebundenTypeNone.IsChecked == true) {
SelectedGraphEntry.SetGebundenFlatBonus(null);
SelectedGraphEntry.RemoveGebundenGraph();
DisableUnitTextBox(GebundenFlatBonus);
RefreshInputs();
} else if (GebundenTypeFixed.IsChecked == true) {
SelectedGraphEntry.SetGebundenFlatBonus(0);
SelectedGraphEntry.RemoveGebundenGraph();
EnableUnitTextBox(GebundenFlatBonus);
RefreshInputs();
} else if (GebundenTypeGraph.IsChecked == true) {
GebundenFlatBonus.Text = "";
SelectedGraphEntry.SetGebundenFlatBonus(null);
SelectedGraphEntry.AddGebundenGraph();
DisableUnitTextBox(GebundenFlatBonus);
RefreshInputs();
}
} }
} }
} }
+3 -3
View File
@@ -148,21 +148,21 @@
</Style> </Style>
</DataGridTextColumn.CellStyle> </DataGridTextColumn.CellStyle>
</DataGridTextColumn> </DataGridTextColumn>
<DataGridTextColumn Header="Sorte" Binding="{Binding SortIdString}" Width="50"> <DataGridTextColumn Header="Sorte" Binding="{Binding FilteredSortIdString}" Width="50">
<DataGridTextColumn.CellStyle> <DataGridTextColumn.CellStyle>
<Style> <Style>
<Setter Property="TextBlock.TextAlignment" Value="Center"/> <Setter Property="TextBlock.TextAlignment" Value="Center"/>
</Style> </Style>
</DataGridTextColumn.CellStyle> </DataGridTextColumn.CellStyle>
</DataGridTextColumn> </DataGridTextColumn>
<DataGridTextColumn Header="Gewicht" Binding="{Binding Weight, StringFormat='{}{0:N0} kg '}" Width="75"> <DataGridTextColumn Header="Gewicht" Binding="{Binding FilteredWeight, StringFormat='{}{0:N0} kg '}" Width="75">
<DataGridTextColumn.CellStyle> <DataGridTextColumn.CellStyle>
<Style> <Style>
<Setter Property="TextBlock.TextAlignment" Value="Right"/> <Setter Property="TextBlock.TextAlignment" Value="Right"/>
</Style> </Style>
</DataGridTextColumn.CellStyle> </DataGridTextColumn.CellStyle>
</DataGridTextColumn> </DataGridTextColumn>
<DataGridTextColumn Header="Gradation" Binding="{Binding Kmw, StringFormat='{}{0:N1}° '}" Width="50"> <DataGridTextColumn Header="Gradation" Binding="{Binding FilteredKmw, StringFormat='{}{0:N1}° '}" Width="50">
<DataGridTextColumn.CellStyle> <DataGridTextColumn.CellStyle>
<Style> <Style>
<Setter Property="TextBlock.TextAlignment" Value="Right"/> <Setter Property="TextBlock.TextAlignment" Value="Right"/>
+43 -32
View File
@@ -10,6 +10,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
@@ -27,7 +28,10 @@ namespace Elwig.Windows {
private Member? Member = null; private Member? Member = null;
private readonly DispatcherTimer Timer; private readonly DispatcherTimer Timer;
private List<string> TextFilter = []; private List<string> TextFilter = [];
private readonly RoutedCommand CtrlF = new();
private readonly RoutedCommand CtrlF = new("CtrlF", typeof(DeliveryAdminWindow), [new KeyGesture(Key.F, ModifierKeys.Control)]);
private readonly RoutedCommand CtrlP = new("CtrlP", typeof(DeliveryAdminWindow), [new KeyGesture(Key.P, ModifierKeys.Control)]);
private readonly RoutedCommand CtrlShiftP = new("CtrlShiftP", typeof(DeliveryAdminWindow), [new KeyGesture(Key.P, ModifierKeys.Control | ModifierKeys.Shift)]);
private string? LastScaleError = null; private string? LastScaleError = null;
private string? ManualWeighingReason = null; private string? ManualWeighingReason = null;
@@ -37,8 +41,9 @@ namespace Elwig.Windows {
public DeliveryAdminWindow(bool receipt = false) { public DeliveryAdminWindow(bool receipt = false) {
InitializeComponent(); InitializeComponent();
CtrlF.InputGestures.Add(new KeyGesture(Key.F, ModifierKeys.Control));
CommandBindings.Add(new CommandBinding(CtrlF, FocusSearchInput)); CommandBindings.Add(new CommandBinding(CtrlF, FocusSearchInput));
CommandBindings.Add(new CommandBinding(CtrlP, Menu_Print_ShowDeliveryNote_Click));
CommandBindings.Add(new CommandBinding(CtrlShiftP, Menu_Print_PrintDeliveryNote_Click));
RequiredInputs = [ RequiredInputs = [
MgNrInput, MemberInput, MgNrInput, MemberInput,
LsNrInput, DateInput, BranchInput, LsNrInput, DateInput, BranchInput,
@@ -168,7 +173,7 @@ namespace Elwig.Windows {
private async void Menu_Print_DeliveryJournal_ShowFilter_Click(object sender, RoutedEventArgs evt) { private async void Menu_Print_DeliveryJournal_ShowFilter_Click(object sender, RoutedEventArgs evt) {
Mouse.OverrideCursor = Cursors.AppStarting; Mouse.OverrideCursor = Cursors.AppStarting;
var (f, _, d, _) = await GetFilters(); var (f, _, d, _, _) = await GetFilters();
var doc = new DeliveryJournal(string.Join(" / ", f), d); var doc = new DeliveryJournal(string.Join(" / ", f), d);
await doc.Generate(); await doc.Generate();
Mouse.OverrideCursor = null; Mouse.OverrideCursor = null;
@@ -177,7 +182,7 @@ namespace Elwig.Windows {
private async void Menu_Print_DeliveryJournal_PrintFilter_Click(object sender, RoutedEventArgs evt) { private async void Menu_Print_DeliveryJournal_PrintFilter_Click(object sender, RoutedEventArgs evt) {
Mouse.OverrideCursor = Cursors.AppStarting; Mouse.OverrideCursor = Cursors.AppStarting;
var (f, _, d, _) = await GetFilters(); var (f, _, d, _, _) = await GetFilters();
var doc = new DeliveryJournal(string.Join(" / ", f), d); var doc = new DeliveryJournal(string.Join(" / ", f), d);
await doc.Generate(); await doc.Generate();
Mouse.OverrideCursor = null; Mouse.OverrideCursor = null;
@@ -296,7 +301,7 @@ namespace Elwig.Windows {
await RefreshDeliveryListQuery(); await RefreshDeliveryListQuery();
} }
private async Task<(List<string>, IQueryable<Delivery>, IQueryable<DeliveryPart>, List<string>)> GetFilters() { private async Task<(List<string>, IQueryable<Delivery>, IQueryable<DeliveryPart>, Predicate<DeliveryPart>, List<string>)> GetFilters() {
List<string> filterNames = []; List<string> filterNames = [];
IQueryable<Delivery> deliveryQuery = Context.Deliveries; IQueryable<Delivery> deliveryQuery = Context.Deliveries;
if (IsReceipt && App.BranchNum > 1) { if (IsReceipt && App.BranchNum > 1) {
@@ -316,12 +321,8 @@ namespace Elwig.Windows {
deliveryQuery = deliveryQuery.Where(d => d.Year == SeasonInput.Value); deliveryQuery = deliveryQuery.Where(d => d.Year == SeasonInput.Value);
filterNames.Add(SeasonInput.Value.ToString() ?? ""); filterNames.Add(SeasonInput.Value.ToString() ?? "");
} }
IQueryable<DeliveryPart> dpq = deliveryQuery
.SelectMany(d => d.Parts) Expression<Func<DeliveryPart, bool>> prd = p => true;
.OrderBy(p => p.Delivery.DateString)
.ThenBy(p => p.Delivery.TimeString)
.ThenBy(p => p.Delivery.LsNr)
.ThenBy(p => p.DPNr);
var filterVar = new List<string>(); var filterVar = new List<string>();
var filterNotVar = new List<string>(); var filterNotVar = new List<string>();
@@ -487,32 +488,32 @@ namespace Elwig.Windows {
} }
} }
if (filterYearGt > 0) dpq = dpq.Where(p => p.Year >= filterYearGt); if (filterYearGt > 0) prd = prd.And(p => p.Year >= filterYearGt);
if (filterYearLt > 0) dpq = dpq.Where(p => p.Year < filterYearLt); if (filterYearLt > 0) prd = prd.And(p => p.Year < filterYearLt);
if (filterMgNr.Count > 0) dpq = dpq.Where(p => filterMgNr.Contains(p.Delivery.MgNr)); if (filterMgNr.Count > 0) prd = prd.And(p => filterMgNr.Contains(p.Delivery.MgNr));
if (filterDate.Count > 0) { if (filterDate.Count > 0) {
var pr = PredicateBuilder.New<DeliveryPart>(false); var pr = PredicateBuilder.New<DeliveryPart>(false);
foreach (var (d1, d2) in filterDate) foreach (var (d1, d2) in filterDate)
pr.Or(p => (d1 == null || d1.CompareTo(p.Delivery.DateString.Substring(10 - d1.Length)) <= 0) && (d2 == null || d2.CompareTo(p.Delivery.DateString.Substring(10 - d2.Length)) >= 0)); pr.Or(p => (d1 == null || d1.CompareTo(p.Delivery.DateString.Substring(10 - d1.Length)) <= 0) && (d2 == null || d2.CompareTo(p.Delivery.DateString.Substring(10 - d2.Length)) >= 0));
dpq = dpq.Where(pr); prd = prd.And(pr);
} }
if (filterTime.Count > 0) { if (filterTime.Count > 0) {
var pr = PredicateBuilder.New<DeliveryPart>(false); var pr = PredicateBuilder.New<DeliveryPart>(false);
foreach (var (t1, t2) in filterTime) foreach (var (t1, t2) in filterTime)
pr.Or(p => (t1 == null || t1.CompareTo(p.Delivery.TimeString) <= 0) && (t2 == null || t2.CompareTo(p.Delivery.TimeString) > 0)); pr.Or(p => (t1 == null || t1.CompareTo(p.Delivery.TimeString) <= 0) && (t2 == null || t2.CompareTo(p.Delivery.TimeString) > 0));
dpq = dpq.Where(p => p.Delivery.TimeString != null).Where(pr); prd = prd.And(p => p.Delivery.TimeString != null).And(pr);
} }
if (filterVar.Count > 0) dpq = dpq.Where(p => filterVar.Contains(p.SortId)); if (filterVar.Count > 0) prd = prd.And(p => filterVar.Contains(p.SortId));
if (filterNotVar.Count > 0) dpq = dpq.Where(p => !filterNotVar.Contains(p.SortId)); if (filterNotVar.Count > 0) prd = prd.And(p => !filterNotVar.Contains(p.SortId));
if (filterQual.Count > 0) dpq = dpq.Where(p => filterQual.Contains(p.QualId)); if (filterQual.Count > 0) prd = prd.And(p => filterQual.Contains(p.QualId));
if (filterNotQual.Count > 0) dpq = dpq.Where(p => !filterNotQual.Contains(p.QualId)); if (filterNotQual.Count > 0) prd = prd.And(p => !filterNotQual.Contains(p.QualId));
if (filterZwst.Count > 0) dpq = dpq.Where(p => filterZwst.Contains(p.Delivery.ZwstId)); if (filterZwst.Count > 0) prd = prd.And(p => filterZwst.Contains(p.Delivery.ZwstId));
if (filterAttr.Count > 0) dpq = dpq.Where(p => p.AttrId != null && filterAttr.Contains(p.AttrId)); if (filterAttr.Count > 0) prd = prd.And(p => p.AttrId != null && filterAttr.Contains(p.AttrId));
if (filterNotAttr.Count > 0) dpq = dpq.Where(p => p.AttrId == null || !filterNotAttr.Contains(p.AttrId)); if (filterNotAttr.Count > 0) prd = prd.And(p => p.AttrId == null || !filterNotAttr.Contains(p.AttrId));
if (filterKmwGt > 0) dpq = dpq.Where(p => p.Kmw >= filterKmwGt); if (filterKmwGt > 0) prd = prd.And(p => p.Kmw >= filterKmwGt);
if (filterKmwLt > 0) dpq = dpq.Where(p => p.Kmw < filterKmwLt); if (filterKmwLt > 0) prd = prd.And(p => p.Kmw < filterKmwLt);
if (filterOeGt > 0) dpq = dpq.Where(p => p.Kmw * (4.54 + 0.022 * p.Kmw) >= filterOeGt); if (filterOeGt > 0) prd = prd.And(p => p.Kmw * (4.54 + 0.022 * p.Kmw) >= filterOeGt);
if (filterOeLt > 0) dpq = dpq.Where(p => p.Kmw * (4.54 + 0.022 * p.Kmw) < filterOeLt); if (filterOeLt > 0) prd = prd.And(p => p.Kmw * (4.54 + 0.022 * p.Kmw) < filterOeLt);
if (filterYearGt > 0 && filterYearLt > 0) { if (filterYearGt > 0 && filterYearLt > 0) {
filterNames.Insert(0, $"{filterYearGt}{filterYearLt - 1}"); filterNames.Insert(0, $"{filterYearGt}{filterYearLt - 1}");
@@ -537,7 +538,15 @@ namespace Elwig.Windows {
} }
} }
return (filterNames, dpq.Select(p => p.Delivery).Distinct().OrderBy(d => d.DateString).ThenBy(d => d.TimeString), dpq, filter); IQueryable<DeliveryPart> dpq = deliveryQuery
.SelectMany(d => d.Parts)
.Where(prd)
.OrderBy(p => p.Delivery.DateString)
.ThenBy(p => p.Delivery.TimeString)
.ThenBy(p => p.Delivery.LsNr)
.ThenBy(p => p.DPNr);
return (filterNames, dpq.Select(p => p.Delivery).Distinct().OrderBy(d => d.DateString).ThenBy(d => d.TimeString), dpq, prd.Invoke, filter);
} }
private static void AddToolTipCell(Grid grid, string text, int row, int col, int colSpan = 1, bool bold = false, bool alignRight = false, bool alignCenter = false) { private static void AddToolTipCell(Grid grid, string text, int row, int col, int colSpan = 1, bool bold = false, bool alignRight = false, bool alignCenter = false) {
@@ -573,7 +582,7 @@ namespace Elwig.Windows {
} }
private async Task RefreshDeliveryListQuery(bool updateSort = false) { private async Task RefreshDeliveryListQuery(bool updateSort = false) {
var (_, deliveryQuery, deliveryPartsQuery, filter) = await GetFilters(); var (_, deliveryQuery, deliveryPartsQuery, predicate, filter) = await GetFilters();
var deliveries = await deliveryQuery.ToListAsync(); var deliveries = await deliveryQuery.ToListAsync();
deliveries.Reverse(); deliveries.Reverse();
@@ -589,8 +598,10 @@ namespace Elwig.Windows {
.ToList(); .ToList();
} }
deliveries.ForEach(d => { d.PartFilter = predicate; });
ControlUtils.RenewItemsSource(DeliveryList, deliveries, d => ((d as Delivery)?.Year, (d as Delivery)?.DId), ControlUtils.RenewItemsSource(DeliveryList, deliveries, d => ((d as Delivery)?.Year, (d as Delivery)?.DId),
DeliveryList_SelectionChanged, filter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort); DeliveryList_SelectionChanged, filter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
await RefreshDeliveryParts();
var members = deliveries.Select(d => d.Member).DistinctBy(m => m.MgNr).ToList(); var members = deliveries.Select(d => d.Member).DistinctBy(m => m.MgNr).ToList();
StatusMembers.Text = $"Mitglieder: {members.Count}" + (members.Count > 0 && members.Count <= 4 ? $" ({string.Join(", ", members.Select(m => m.AdministrativeName))})" : ""); StatusMembers.Text = $"Mitglieder: {members.Count}" + (members.Count > 0 && members.Count <= 4 ? $" ({string.Join(", ", members.Select(m => m.AdministrativeName))})" : "");
@@ -722,7 +733,7 @@ namespace Elwig.Windows {
Menu_Export_Bki.Items.Clear(); Menu_Export_Bki.Items.Clear();
foreach (var s in await Context.Seasons.OrderByDescending(s => s.Year).ToListAsync()) { foreach (var s in await Context.Seasons.OrderByDescending(s => s.Year).ToListAsync()) {
var i = new MenuItem { var i = new MenuItem {
Header = $"Season {s.Year}", Header = $"Saison {s.Year}",
}; };
i.Click += Menu_Export_Bki_Click; i.Click += Menu_Export_Bki_Click;
Menu_Export_Bki.Items.Add(i); Menu_Export_Bki.Items.Add(i);
@@ -760,7 +771,7 @@ namespace Elwig.Windows {
private async Task RefreshDeliveryParts() { private async Task RefreshDeliveryParts() {
if (DeliveryList.SelectedItem is Delivery d) { if (DeliveryList.SelectedItem is Delivery d) {
ControlUtils.RenewItemsSource(ModifiersInput, await Context.Modifiers.Where(m => m.Year == d.Year).OrderBy(m => m.Ordering).ToListAsync(), i => (i as Modifier)?.ModId); ControlUtils.RenewItemsSource(ModifiersInput, await Context.Modifiers.Where(m => m.Year == d.Year).OrderBy(m => m.Ordering).ToListAsync(), i => (i as Modifier)?.ModId);
ControlUtils.RenewItemsSource(DeliveryPartList, d.Parts.OrderBy(p => p.DPNr).ToList(), i => ((i as DeliveryPart)?.Year, (i as DeliveryPart)?.DId, (i as DeliveryPart)?.DPNr), DeliveryPartList_SelectionChanged, ControlUtils.RenewSourceDefault.First); ControlUtils.RenewItemsSource(DeliveryPartList, d.FilteredParts.OrderBy(p => p.DPNr).ToList(), i => ((i as DeliveryPart)?.Year, (i as DeliveryPart)?.DId, (i as DeliveryPart)?.DPNr), DeliveryPartList_SelectionChanged, ControlUtils.RenewSourceDefault.First);
} else { } else {
ControlUtils.RenewItemsSource(ModifiersInput, await Context.Modifiers.Where(m => m.Year == Utils.CurrentLastSeason).OrderBy(m => m.Ordering).ToListAsync(), i => (i as Modifier)?.ModId); ControlUtils.RenewItemsSource(ModifiersInput, await Context.Modifiers.Where(m => m.Year == Utils.CurrentLastSeason).OrderBy(m => m.Ordering).ToListAsync(), i => (i as Modifier)?.ModId);
DeliveryPartList.ItemsSource = null; DeliveryPartList.ItemsSource = null;
@@ -1134,7 +1145,7 @@ namespace Elwig.Windows {
} else { } else {
// switch to last delivery part // switch to last delivery part
DeliveryPartList.IsEnabled = true; DeliveryPartList.IsEnabled = true;
DeliveryPartList.SelectedItem = d.Parts.Last(); DeliveryPartList.SelectedItem = d.FilteredParts.Last();
} }
} }
+6 -2
View File
@@ -17,15 +17,19 @@ namespace Elwig.Windows {
public partial class MemberAdminWindow : AdministrationWindow { public partial class MemberAdminWindow : AdministrationWindow {
private List<string> TextFilter = []; private List<string> TextFilter = [];
private readonly RoutedCommand CtrlF = new();
private readonly (ComboBox, TextBox, TextBox)[] PhoneNrInputs; private readonly (ComboBox, TextBox, TextBox)[] PhoneNrInputs;
private readonly RoutedCommand CtrlF = new("CtrlF", typeof(MemberAdminWindow), [new KeyGesture(Key.F, ModifierKeys.Control)]);
private readonly RoutedCommand CtrlP = new("CtrlP", typeof(MemberAdminWindow), [new KeyGesture(Key.P, ModifierKeys.Control)]);
private readonly RoutedCommand CtrlShiftP = new("CtrlShiftP", typeof(MemberAdminWindow), [new KeyGesture(Key.P, ModifierKeys.Control | ModifierKeys.Shift)]);
private static ObservableCollection<KeyValuePair<string, string>> PhoneNrTypes { get; set; } = new(Utils.PhoneNrTypes); private static ObservableCollection<KeyValuePair<string, string>> PhoneNrTypes { get; set; } = new(Utils.PhoneNrTypes);
public MemberAdminWindow() { public MemberAdminWindow() {
InitializeComponent(); InitializeComponent();
CtrlF.InputGestures.Add(new KeyGesture(Key.F, ModifierKeys.Control));
CommandBindings.Add(new CommandBinding(CtrlF, FocusSearchInput)); CommandBindings.Add(new CommandBinding(CtrlF, FocusSearchInput));
CommandBindings.Add(new CommandBinding(CtrlP, Menu_Show_MemberDataSheet_Click));
CommandBindings.Add(new CommandBinding(CtrlShiftP, Menu_Print_MemberDataSheet_Click));
ExemptInputs = [ ExemptInputs = [
SearchInput, ActiveMemberInput, MemberList, SearchInput, ActiveMemberInput, MemberList,
]; ];
+1 -1
View File
@@ -13,7 +13,7 @@
<EmbeddedResource Include="Resources\*.sql" /> <EmbeddedResource Include="Resources\*.sql" />
</ItemGroup> </ItemGroup>
<Target Name="PreBuild" BeforeTargets="PreBuildEvent"> <Target Name="FetchResources" BeforeTargets="BeforeBuild">
<Exec Command="call fetch-resources.bat" /> <Exec Command="call fetch-resources.bat" />
</Target> </Target>