ChartWindow: Use BillingData and Curve

This commit is contained in:
2024-01-17 14:33:21 +01:00
parent b52c09a176
commit b6fd62f8ca
3 changed files with 159 additions and 136 deletions

View File

@ -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());
}
}
}

View File

@ -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>

View File

@ -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();