ChartWindow: Use BillingData and Curve
This commit is contained in:
@ -7,18 +7,18 @@ using System.Text.Json.Nodes;
|
||||
namespace Elwig.Helpers.Billing {
|
||||
public class Graph : ICloneable {
|
||||
|
||||
public string Type { get; set; }
|
||||
public int Num { get; set; }
|
||||
public BillingData.CurveMode Mode { get; set; }
|
||||
public int Id { get; set; }
|
||||
private int MinX { get; set; }
|
||||
private int MaxX { get; set; }
|
||||
public string Contracts { get; set; }
|
||||
public List<Tuple<string, string>> Contracts { get; set; }
|
||||
public double[] DataX { get; set; }
|
||||
public double[] DataY { get; set; }
|
||||
|
||||
public Graph(int num, int minX, int maxX) {
|
||||
Type = "oe";
|
||||
Num = num;
|
||||
Contracts = "";
|
||||
public Graph(int id, BillingData.CurveMode mode, int minX, int maxX) {
|
||||
Id = id;
|
||||
Mode = mode;
|
||||
Contracts = new List<Tuple<string, string>>();
|
||||
MinX = minX;
|
||||
MaxX = maxX;
|
||||
|
||||
@ -26,21 +26,21 @@ namespace Elwig.Helpers.Billing {
|
||||
DataY = DataGen.Zeros(MaxX - MinX + 1);
|
||||
}
|
||||
|
||||
public Graph(string type, int num, JsonObject graphData, string contracts, int minX, int maxX) {
|
||||
Type = type;
|
||||
Num = num;
|
||||
Contracts = contracts;
|
||||
public Graph(int id, BillingData.CurveMode mode, Dictionary<double, decimal> data, int minX, int maxX) {
|
||||
Id = id;
|
||||
Mode = mode;
|
||||
Contracts = new List<Tuple<string, string>>();
|
||||
MinX = minX;
|
||||
MaxX = maxX;
|
||||
|
||||
DataX = DataGen.Range(MinX, MaxX + 1);
|
||||
DataY = DataGen.Zeros(MaxX - MinX + 1);
|
||||
ParseGraphData(graphData);
|
||||
ParseGraphData(data);
|
||||
}
|
||||
|
||||
public Graph(string type, int num, int minX, int maxX, string contracts, double[] dataX, double[] dataY) {
|
||||
Type = type;
|
||||
Num = num;
|
||||
public Graph(int id, BillingData.CurveMode mode, int minX, int maxX, List<Tuple<string, string>> contracts, double[] dataX, double[] dataY) {
|
||||
Id = id;
|
||||
Mode = mode;
|
||||
MinX = minX;
|
||||
MaxX = maxX;
|
||||
Contracts = contracts;
|
||||
@ -48,72 +48,78 @@ namespace Elwig.Helpers.Billing {
|
||||
DataY = dataY;
|
||||
}
|
||||
|
||||
private void ParseGraphData(JsonObject graphData) {
|
||||
var GraphPoints = graphData.ToDictionary(p => int.Parse(p.Key[..^2]), p => (double)p.Value?.AsValue());
|
||||
|
||||
if (GraphPoints.Keys.Count < 1) {
|
||||
private void ParseGraphData(Dictionary<double, decimal> graphPoints) {
|
||||
if (graphPoints.Keys.Count < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
var minKey = GraphPoints.Keys.Order().First();
|
||||
var maxKey = GraphPoints.Keys.OrderDescending().First();
|
||||
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(MinX)) {
|
||||
graphPoints.Add(MinX, graphPoints.GetValueOrDefault(minKey));
|
||||
}
|
||||
if (!GraphPoints.ContainsKey(MaxX)) {
|
||||
GraphPoints.Add(MaxX, GraphPoints.GetValueOrDefault(maxKey));
|
||||
if (!graphPoints.ContainsKey(MaxX)) {
|
||||
graphPoints.Add(MaxX, graphPoints.GetValueOrDefault(maxKey));
|
||||
}
|
||||
|
||||
var keys = GraphPoints.Keys.Order().ToArray();
|
||||
var keys = graphPoints.Keys.Order().ToArray();
|
||||
|
||||
for (int i = 0; i < keys.Length; i++) {
|
||||
double point1Value = GraphPoints[keys[i]];
|
||||
decimal point1Value = graphPoints[keys[i]];
|
||||
if (i + 1 < keys.Length) {
|
||||
double point2Value = GraphPoints[keys[i + 1]];
|
||||
decimal point2Value = graphPoints[keys[i + 1]];
|
||||
if (point1Value == point2Value) {
|
||||
for (int j = keys[i] - MinX; j < keys[i + 1] - MinX; j++) {
|
||||
DataY[j] = point1Value;
|
||||
for (int j = (int)(keys[i] - MinX); j < keys[i + 1] - MinX; j++) {
|
||||
DataY[j] = (double)point1Value;
|
||||
}
|
||||
} else {
|
||||
int steps = Math.Abs(keys[i + 1] - keys[i]);
|
||||
double step = (point2Value - point1Value) / steps;
|
||||
int steps = (int)Math.Abs(keys[i + 1] - keys[i]);
|
||||
decimal step = (point2Value - point1Value) / steps;
|
||||
|
||||
DataY[keys[i] - MinX] = point1Value;
|
||||
DataY[keys[i + 1] - MinX] = point2Value;
|
||||
DataY[(int)(keys[i] - MinX)] = (double)point1Value;
|
||||
DataY[(int)(keys[i + 1] - MinX)] = (double)point2Value;
|
||||
|
||||
for (int j = keys[i] - MinX; j < keys[i + 1] - MinX - 1; j++) {
|
||||
DataY[j + 1] = Math.Round(DataY[j] + step, 4); // TODO richtig runden
|
||||
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 = keys[i] - MinX; j < DataX.Length; j++) {
|
||||
DataY[j] = point1Value;
|
||||
for (int j = (int)(keys[i] - MinX); j < DataX.Length; j++) {
|
||||
DataY[j] = (double)point1Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public JsonObject ToJson() {
|
||||
JsonObject graph = new();
|
||||
var graph = new JsonObject {
|
||||
["id"] = Id,
|
||||
["mode"] = Mode.ToString().ToLower(),
|
||||
};
|
||||
|
||||
var data = new JsonObject();
|
||||
|
||||
if (DataY[0] != DataY[1]) {
|
||||
graph.Add(new KeyValuePair<string, JsonNode?>(DataX[0] + Type.ToLower(), Math.Round(DataY[0], 4)));
|
||||
data.Add(new KeyValuePair<string, JsonNode?>(DataX[0] + Mode.ToString().ToLower(), Math.Round(DataY[0], 4)));
|
||||
}
|
||||
for (int i = 1; i < DataX.Length - 1; i++) {
|
||||
if (Math.Round(DataY[i] - DataY[i - 1], 4) != Math.Round(DataY[i + 1] - DataY[i], 4)) {
|
||||
graph.Add(new KeyValuePair<string, JsonNode?>(DataX[i] + Type.ToLower(), Math.Round(DataY[i], 4)));
|
||||
if (Math.Round(DataY[i] - DataY[i - 1], 10) != Math.Round(DataY[i + 1] - DataY[i], 10)) {
|
||||
data.Add(new KeyValuePair<string, JsonNode?>(DataX[i] + Mode.ToString().ToLower(), Math.Round(DataY[i], 4)));
|
||||
}
|
||||
}
|
||||
if (DataY[^1] != DataY[^2]) {
|
||||
graph.Add(new KeyValuePair<string, JsonNode?>(DataX[^1] + Type.ToLower(), Math.Round(DataY[^1], 4)));
|
||||
data.Add(new KeyValuePair<string, JsonNode?>(DataX[^1] + Mode.ToString().ToLower(), Math.Round(DataY[^1], 4)));
|
||||
}
|
||||
|
||||
graph["data"] = data;
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
public object Clone() {
|
||||
return new Graph(Type, Num, MinX, MaxX, Contracts, (double[])DataX.Clone(), (double[])DataY.Clone());
|
||||
return new Graph(Id, Mode, MinX, MaxX, Contracts.ConvertAll(item => new Tuple<string, string>(item.Item1, item.Item2)), (double[])DataX.Clone(), (double[])DataY.Clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,14 +68,14 @@
|
||||
SelectionChanged="GraphList_SelectionChanged"
|
||||
Margin="5,15,5,0" Grid.Row="0" FontSize="14" Grid.ColumnSpan="3">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Nr." Binding="{Binding Num}" Width="40">
|
||||
<DataGridTextColumn Header="Nr." Binding="{Binding Id}" Width="40">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style>
|
||||
<Setter Property="TextBlock.TextWrapping" Value="Wrap" />
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Header="Typ" Binding="{Binding Type}" Width="40"/>
|
||||
<DataGridTextColumn Header="Modus" Binding="{Binding Mode}" Width="40"/>
|
||||
<DataGridTextColumn Header="Angewandte Verträge" Binding="{Binding Contracts}" Width="4*"/>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
@ -75,27 +75,15 @@ namespace Elwig.Windows {
|
||||
var data = ParseData(paymentVar);
|
||||
if (data == null) return;
|
||||
|
||||
var auszahlungsSorten = data["AuszahlungSorten"]?.AsObject();
|
||||
if (auszahlungsSorten == null) {
|
||||
return;
|
||||
var curves = BillingData.GetCurves(data, BillingData.CalculationMode.Elwig);
|
||||
List<Graph> graphs = [];
|
||||
|
||||
foreach (var (id, curve) in curves) {
|
||||
graphs.Add(new Graph(id, curve.Mode, curve.Normal, MinOechsle, MaxOechsle));
|
||||
}
|
||||
|
||||
var Graphs = auszahlungsSorten["Kurven"]?.AsArray();
|
||||
|
||||
if (Graphs == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Graph> GraphsList = [];
|
||||
|
||||
int i = 1;
|
||||
foreach (var graph in Graphs) {
|
||||
GraphsList.Add(new Graph("Oe", i, graph?.AsObject(), ParseContracts(auszahlungsSorten, i - 1), 50, 140));
|
||||
i++;
|
||||
}
|
||||
|
||||
ControlUtils.RenewItemsSource(GraphList, GraphsList, g => (g as Graph)?.Num);
|
||||
if (GraphsList.Count == 1) {
|
||||
ControlUtils.RenewItemsSource(GraphList, graphs, g => (g as Graph)?.Id);
|
||||
if (graphs.Count == 1) {
|
||||
GraphList.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
@ -125,46 +113,63 @@ namespace Elwig.Windows {
|
||||
var data = ParseData(paymentVar);
|
||||
if (data == null) return false;
|
||||
|
||||
var auszahlungsSorten = data["AuszahlungSorten"]?.AsObject();
|
||||
if (auszahlungsSorten == null) {
|
||||
MessageBox.Show("1");
|
||||
|
||||
|
||||
JsonArray? curves;
|
||||
JsonObject? payment;
|
||||
|
||||
if (data["mode"]?.GetValue<string>() == "elwig") {
|
||||
curves = data["curves"]?.AsArray();
|
||||
payment = data["payment"]?.AsObject();
|
||||
} else if (data["mode"]?.GetValue<string>() == "wgmaster") {
|
||||
curves = data["Kurven"]?.AsArray();
|
||||
payment = data["AuszahlungSorten"]?.AsObject();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
var Graphs = auszahlungsSorten["Kurven"]?.AsObject();
|
||||
if (Graphs == null) {
|
||||
MessageBox.Show("2");
|
||||
|
||||
|
||||
if (curves == null || payment == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int i = 1;
|
||||
foreach (var graph in Graphs) {
|
||||
if (i == num) {
|
||||
Graphs.Remove(graph.Key);
|
||||
MessageBox.Show("3");
|
||||
|
||||
foreach (var curve in curves) {
|
||||
MessageBox.Show("LOOP");
|
||||
if (curve?.AsObject()?["id"]?.GetValue<int>() == num) {
|
||||
MessageBox.Show(curve.ToJsonString());
|
||||
curves.Remove(curve);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
foreach (var sorte in auszahlungsSorten) {
|
||||
if (sorte.Key == "Kurven") continue;
|
||||
foreach (var attribut in sorte.Value.AsObject()) {
|
||||
var bindungen = attribut.Value.AsObject();
|
||||
foreach (var bindung in bindungen) {
|
||||
int v = (int)bindung.Value;
|
||||
if (v == num - 1) {
|
||||
bindungen.Remove(bindung.Key);
|
||||
} else if (v > num - 1) {
|
||||
bindungen[bindung.Key] = v - 1;
|
||||
}
|
||||
MessageBox.Show("4");
|
||||
|
||||
var keysToRemove = new List<string>();
|
||||
foreach (var sorte in payment) {
|
||||
MessageBox.Show(sorte.Value.GetType().ToString());
|
||||
if (sorte.Value.AsValue().TryGetValue(out string? curve) && curve.Equals($"curve:{num}")) {
|
||||
keysToRemove.Add(sorte.Key);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var key in keysToRemove) {
|
||||
payment.Remove(key);
|
||||
}
|
||||
|
||||
MessageBox.Show("5");
|
||||
|
||||
EntityEntry<PaymentVar>? tr = null;
|
||||
try {
|
||||
paymentVar.Data = data.ToString();
|
||||
tr = Context.Update(paymentVar);
|
||||
|
||||
await Context.SaveChangesAsync();
|
||||
await App.HintContextChange();
|
||||
} catch (Exception exc) {
|
||||
if (tr != null) await tr.ReloadAsync();
|
||||
var str = "Der Eintrag konnte nicht in der Datenbank gelöscht werden!\n\n" + exc.Message;
|
||||
@ -175,6 +180,62 @@ namespace Elwig.Windows {
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<int?> UpdateGraph(Graph g) {
|
||||
var paymentVar = await Context.PaymentVariants.FindAsync(Year, AvNr);
|
||||
if (paymentVar == null) return null;
|
||||
|
||||
var data = ParseData(paymentVar);
|
||||
if (data == null) return null;
|
||||
|
||||
JsonArray? curves;
|
||||
JsonObject? payment;
|
||||
|
||||
if (data["mode"]?.GetValue<string>() == "elwig") {
|
||||
curves = data["curves"]?.AsArray();
|
||||
payment = data["payment"]?.AsObject();
|
||||
} else if (data["mode"]?.GetValue<string>() == "wgmaster") {
|
||||
curves = data["Kurven"]?.AsArray();
|
||||
payment = data["AuszahlungSorten"]?.AsObject();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (curves == null || payment == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (IsEditing) {
|
||||
int i = 0;
|
||||
foreach (var curve in curves) {
|
||||
if (curve?.AsObject()?["id"]?.GetValue<int>() == g.Id) {
|
||||
curves[i] = g.ToJson();
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
} else if(IsCreating) {
|
||||
curves.Add(g.ToJson());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
EntityEntry<PaymentVar>? tr = null;
|
||||
try {
|
||||
paymentVar.Data = data.ToString();
|
||||
tr = Context.Update(paymentVar);
|
||||
|
||||
await Context.SaveChangesAsync();
|
||||
await App.HintContextChange();
|
||||
} catch (Exception exc) {
|
||||
if (tr != null) await tr.ReloadAsync();
|
||||
var str = "Der Eintrag konnte nicht in der Datenbank gelöscht werden!\n\n" + exc.Message;
|
||||
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
||||
MessageBox.Show(str, "Graph löschen", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
|
||||
return g.Id;
|
||||
}
|
||||
|
||||
private void RefreshInputs(bool validate = false) {
|
||||
ResetPlot();
|
||||
ClearInputStates();
|
||||
@ -199,10 +260,10 @@ namespace Elwig.Windows {
|
||||
|
||||
Graph = (Graph)g.Clone();
|
||||
|
||||
GraphNumberInput.Text = Graph.Num.ToString();
|
||||
if (Graph.Type == "oe") {
|
||||
GraphNumberInput.Text = Graph.Id.ToString();
|
||||
if (Graph.Mode == BillingData.CurveMode.Oe) {
|
||||
OechsleGraphType_Input.IsChecked = true;
|
||||
} else if (Graph.Type == "kmw") {
|
||||
} else if (Graph.Mode == BillingData.CurveMode.Kmw) {
|
||||
KmwGraphType_Input.IsChecked = true;
|
||||
}
|
||||
|
||||
@ -604,7 +665,7 @@ namespace Elwig.Windows {
|
||||
PriceInput.IsReadOnly = false;
|
||||
OechsleInput.IsReadOnly = false;
|
||||
InitInputs();
|
||||
FillInputs(new Graph(GraphList.Items.Count + 1, MinOechsle, MaxOechsle));
|
||||
FillInputs(new Graph(GraphList.Items.Count + 1, BillingData.CurveMode.Oe, MinOechsle, MaxOechsle)); //TODO not hardcode oe
|
||||
EnableOptionButtons();
|
||||
}
|
||||
|
||||
@ -629,10 +690,10 @@ namespace Elwig.Windows {
|
||||
if (g == null) return;
|
||||
|
||||
var r = MessageBox.Show(
|
||||
$"Soll der Graph {g.Num} (verwendet in folgenden Verträgen: {g.Contracts}) wirklich unwiderruflich gelöscht werden?",
|
||||
$"Soll der Graph {g.Id} (verwendet in folgenden Verträgen: {g.Contracts}) wirklich unwiderruflich gelöscht werden?",
|
||||
"Graph löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
|
||||
if (r == MessageBoxResult.Yes) {
|
||||
bool success = await RemoveGraph(g.Num);
|
||||
bool success = await RemoveGraph(g.Id);
|
||||
if (!success) {
|
||||
MessageBox.Show("Der Graph konnte nicht gelöscht werden", "Graph löschen", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
@ -658,50 +719,6 @@ namespace Elwig.Windows {
|
||||
GraphList.SelectedIndex = index.Value;
|
||||
}
|
||||
|
||||
private async Task<int?> UpdateGraph(Graph g) {
|
||||
List<PaymentVar> paymentVars = await Context.PaymentVariants.Where(p => p.Year == Year && p.AvNr == AvNr).ToListAsync();
|
||||
|
||||
if (paymentVars.Count != 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PaymentVar paymentVar = paymentVars[0];
|
||||
var data = JsonNode.Parse(paymentVar.Data).AsObject();
|
||||
|
||||
var auszahlungsSorten = data["AuszahlungSorten"];
|
||||
if (auszahlungsSorten == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var Graphs = auszahlungsSorten["Kurven"].AsArray();
|
||||
if (Graphs == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (IsEditing) {
|
||||
Graphs[g.Num - 1] = g.ToJson();
|
||||
} else if(IsCreating) {
|
||||
Graphs.Add(g.ToJson());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
EntityEntry<PaymentVar>? tr = null;
|
||||
try {
|
||||
paymentVar.Data = data.ToString();
|
||||
tr = Context.Update(paymentVar);
|
||||
|
||||
await Context.SaveChangesAsync();
|
||||
} catch (Exception exc) {
|
||||
if (tr != null) await tr.ReloadAsync();
|
||||
var str = "Der Eintrag konnte nicht in der Datenbank gelöscht werden!\n\n" + exc.Message;
|
||||
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
||||
MessageBox.Show(str, "Graph löschen", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
|
||||
return g.Num - 1;
|
||||
}
|
||||
|
||||
private void ResetButton_Click(object sender, RoutedEventArgs e) {
|
||||
if (IsEditing) {
|
||||
RefreshInputs();
|
||||
|
Reference in New Issue
Block a user