Billing: Split BillingData into BillingData and PaymentBillingData
This commit is contained in:
131
Elwig/Helpers/Billing/PaymentBillingData.cs
Normal file
131
Elwig/Helpers/Billing/PaymentBillingData.cs
Normal file
@ -0,0 +1,131 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace Elwig.Helpers.Billing {
|
||||
public class PaymentBillingData : BillingData {
|
||||
|
||||
protected readonly Dictionary<int, Curve> Curves;
|
||||
protected readonly Dictionary<string, Curve> PaymentData;
|
||||
protected readonly Dictionary<string, Curve> QualityData;
|
||||
protected readonly IEnumerable<string> AttributeVariants;
|
||||
|
||||
public PaymentBillingData(JsonObject data, IEnumerable<string> attributeVariants) :
|
||||
base(data) {
|
||||
if (attributeVariants.Any(e => e.Any(c => c < 'A' || c > 'Z')))
|
||||
throw new ArgumentException("Invalid attributeVariants");
|
||||
AttributeVariants = attributeVariants;
|
||||
Curves = GetCurves();
|
||||
PaymentData = GetPaymentData();
|
||||
QualityData = GetQualityData();
|
||||
}
|
||||
|
||||
public static PaymentBillingData FromJson(string json, IEnumerable<string> attributeVariants) {
|
||||
return new(ParseJson(json), attributeVariants);
|
||||
}
|
||||
|
||||
private Dictionary<string, Curve> GetData(JsonObject data) {
|
||||
Dictionary<string, Curve> dict;
|
||||
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() {
|
||||
var p = 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() {
|
||||
Dictionary<string, Curve> dict = [];
|
||||
var q = GetQualityEntry();
|
||||
|
||||
foreach (var (qualid, data) in q) {
|
||||
Dictionary<string, Curve> qualDict;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
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 d = (gebunden ? curve.Gebunden : null) ?? curve.Normal;
|
||||
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) {
|
||||
if (val.TryGetValue(out string? curve)) {
|
||||
var curveId = int.Parse(curve.Split(":")[1]);
|
||||
return Curves[curveId];
|
||||
} else if (val.TryGetValue(out decimal value)) {
|
||||
return new(CurveMode.Oe, new() { { 73, value } }, null);
|
||||
}
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
protected Curve GetCurve(string sortid, string? attrid) {
|
||||
return PaymentData[$"{sortid}{attrid ?? ""}"];
|
||||
}
|
||||
|
||||
protected Curve? GetQualityCurve(string qualid, string sortid, string? attrid) {
|
||||
return QualityData.TryGetValue($"{qualid}/{sortid}{attrid ?? ""}", out var curve) ? curve : null;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user