Compare commits
21 Commits
v0.6.0
...
182b367811
| Author | SHA1 | Date | |
|---|---|---|---|
| 182b367811 | |||
| a2bb09cfbd | |||
| b981b5f895 | |||
| 9dc2e8a59a | |||
| 1dc05e47cf | |||
| 21cc20ee63 | |||
| 491c41b239 | |||
| 47658a72ae | |||
| 8b0a4d7979 | |||
| 9ee7f6baf1 | |||
| ecbc9c2d82 | |||
| bf90543ad8 | |||
| 6a5676f916 | |||
| 75e9d756d2 | |||
| ee161b149b | |||
| 0cb7b4bfc8 | |||
| 4a49a17b6a | |||
| 741ccaacae | |||
| 19f4300440 | |||
| 954c7a8bdb | |||
| 626724fe87 |
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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() ?? []) {
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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?[] {
|
||||||
|
|||||||
@@ -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="" FontFamily="Segoe MDL2 Assets" FontSize="11" Padding="0,1.5,0,0" ToolTip="Neue Auszahlungsvariante hinzufügen"
|
<Button x:Name="AddButton" Content="" 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="" FontFamily="Segoe MDL2 Assets" FontSize="12" Padding="0,0,0,0" IsEnabled="False" ToolTip="Ausgewählte Auszahlungsvariante duplizieren"
|
<Button x:Name="CopyButton" Content="" 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="" 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="" 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
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"/>
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user