Gremlin/Gremlin_BlazorServer/Services/QuoteHandling.cs

228 lines
8.4 KiB
C#

using System.Globalization;
using System.Text;
using Gremlin_BlazorServer.Data.EntityClasses;
using Gremlin_BlazorServer.Pages.Quotes;
namespace Gremlin_BlazorServer.Services;
public class QuoteHandling {
private static readonly GenericController genericController = new();
private readonly IWebHostEnvironment hostingEnvironment;
public static async Task<StringBuilder?> CreateTexAsync(Quote quote) {
StringBuilder? texString = await TexService.CreateTex(quote);
if (texString is null) return null;
Console.WriteLine(texString.Length > 0 ? "Creating TexFile succesfully." : "Error during TexFile creation!");
return texString;
}
//FromWindowsGremlin
private Quote ReadLineItems(Quote quote, string clipboard) {
try {
quote = ResetTotals(quote);
quote.LineItems = ReadLineItemsFromClipboard(clipboard);
quote.QuoteContains3Pp = DoesContains(quote, "3PP");
quote.QuoteContainsRb = DoesContains(quote, "RB");
quote.TotalListprice = GetTotal(quote, "TotalListprice");
quote.TotalDiscount = GetTotal(quote, "AverageDiscount");
quote.TotalNet = GetTotal(quote, "TotalNet");
if (quote.Recipient?.Account != null) quote.ValidFor = CheckForAcademic(quote.Recipient.Account);
foreach (LineItem lineItem in quote.LineItems) {
if (lineItem.OptionNumber == null) break;
if (lineItem.OptionNumber.StartsWith("8D")) quote.Warranty = int.Parse(lineItem.OptionNumber.Last().ToString()) * 12;
quote.Warranty = lineItem.OptionNumber switch {
"9EC" => 24,
"9CC" => 36,
_ => quote.Warranty
};
}
quote = CalculateTotals(quote);
return quote;
}
catch (Exception e) {
Console.WriteLine(e);
return new();
}
}
private List<LineItem> ReadLineItemsFromClipboard(string clipboard) {
//Zeilen aufteilen
IEnumerable<string> clipboardLines = clipboard.Split(Environment.NewLine.ToCharArray());
List<string[]> clipboardList = (from clipboardLine in clipboardLines where clipboardLine != "" select clipboardLine.Split('\t')).ToList();
List<LineItem> lineItems = ParseClipboardList(clipboardList).Result;
return lineItems;
}
private async Task<List<LineItem>> ParseClipboardList(List<string[]> lineItemStrings) {
List<LineItem> lineItems = new();
CultureInfo cultureInfoUs = new("en-US");
foreach (string[] lineItemString in lineItemStrings)
//Anzahl an Spalten entspricht Clipboard
if (lineItemString.Length == 19) {
//Header ignorieren
if (lineItemString[0] == "#") continue;
//Dateiinhalt in Klasse schreiben
LineItem lineItem = new() {
Position = ushort.Parse(lineItemString[0]),
ProductNumber = lineItemString[1],
OptionNumber = lineItemString[2],
ProductLine = lineItemString[3],
SapShortDescription = lineItemString[4],
Amount = ushort.Parse(lineItemString[5]),
ListPrice = decimal.Parse(lineItemString[6], cultureInfoUs),
TotalDiscount = decimal.Parse(lineItemString[9], cultureInfoUs),
NetPrice = decimal.Parse(lineItemString[10], cultureInfoUs),
Total = decimal.Parse(lineItemString[11], cultureInfoUs),
SalesDiscount = decimal.Parse(lineItemString[12], cultureInfoUs),
ContractualDiscount = decimal.Parse(lineItemString[13], cultureInfoUs),
PromotionalDiscount = decimal.Parse(lineItemString[14], cultureInfoUs),
DemoDiscount = decimal.Parse(lineItemString[15], cultureInfoUs)
};
lineItems.Add(lineItem);
}
else {
Console.WriteLine("Angebot konnte nicht eingelesen werden!");
}
return lineItems;
}
private byte CheckForAcademic(Account account) {
return account.AccountType?.AccountTypeCode == null ? (byte)60 : (byte)(account.AccountType.AccountTypeCode.StartsWith("N") ? 90 : 60);
}
private decimal GetFreight(decimal net, decimal freight) {
decimal freightNet = net * freight / 100;
return freightNet < 3000 ? freightNet : 3000;
}
private Quote CalculateTotals(Quote quote) {
quote.TotalFreightOnly = GetFreight(quote.TotalNet, quote.Freight);
quote.TotalFreight = quote.TotalNet + quote.TotalFreightOnly;
quote.TotalVat = quote.TotalFreight * Convert.ToDecimal(quote.Vat) / 100;
quote.TotalGross = quote.TotalFreight * (100 + Convert.ToDecimal(quote.Vat)) / 100;
return quote;
}
private Quote ResetTotals(Quote quote) {
quote.TotalListprice = 0;
quote.TotalNet = 0;
quote.TotalFreightOnly = 0;
quote.TotalFreight = 0;
quote.TotalVat = 0;
quote.TotalGross = 0;
return quote;
}
private decimal GetTotal(Quote quote, string type) {
decimal total = 0;
if (quote.LineItems == null) return total;
foreach (LineItem lineItem in quote.LineItems)
switch (type) {
case "TotalListprice":
total += lineItem.ListPrice;
break;
case "TotalNet":
total += lineItem.Total;
break;
case "AverageDiscount":
total += lineItem.TotalDiscount;
break;
}
if ((type == "AverageDiscount") & (quote.LineItems.Count != 0)) total /= quote.LineItems.Count;
return total;
}
private bool DoesContains(Quote quote, string type) {
if (quote.LineItems is null) return false;
foreach (LineItem lineItem in quote.LineItems)
switch (type) {
case "3PP":
if (lineItem.ProductLine == "3PP") {
Console.WriteLine($"Quote contains 3PP with ProductNumber {lineItem.ProductNumber}");
return true;
}
break;
case "RB":
if ((lineItem.ProductLine == "RB") & (lineItem.ProductNumber != "R2005A")) {
Console.WriteLine($"Quote contains RB with ProductNumber {lineItem.ProductNumber}");
return true;
}
break;
}
return false;
}
public async Task<Quote> GenerateQuoteFromString(Quote quote, string fileContent) {
HostingService hostingService = new(hostingEnvironment);
quote = ReadLineItems(quote, fileContent);
if (quote.Recipient?.Account?.AccountName is not null) quote = hostingService.SetPath(quote);
if (quote.LineItems is null) return quote;
FileService.WriteQuoteToTsv(fileContent, quote);
//TODO Load all relevant CustomDescriptions upfront
foreach (LineItem lineItem in quote.LineItems) {
CustomDescription newCustomDescription = await genericController.GetAsync<CustomDescription>(newCustomDescription => newCustomDescription.ProductNumber.Equals(lineItem.ProductNumber, StringComparison.Ordinal) && newCustomDescription.OptionNumber.Equals(lineItem.OptionNumber, StringComparison.Ordinal));
if (newCustomDescription is null) {
Console.WriteLine($"Keine CustomDescription für {lineItem.ProductNumber}#{lineItem.OptionNumber} verfügbar!");
List<CustomDescription>? suggestedCustomDescriptions = await SuggestCustomDescriptions(lineItem);
newCustomDescription = new() {
ProductNumber = lineItem.ProductNumber,
OptionNumber = lineItem.OptionNumber,
Heading = lineItem.SapShortDescription,
DescriptionText = lineItem.SapLongDescription
};
//Show windows to edit new cD
await QuoteAdd.ShowCustomDescriptionModal(suggestedCustomDescriptions);
//TODO need to wait for modal!
//Insert new CustomDescription to db
newCustomDescription.AccountId = 1;
_ = await genericController.InsertAsync(newCustomDescription);
}
lineItem.Product = await genericController.GetAsync<Product>(p => p.ProductNumber.Equals(lineItem.ProductNumber) && p.OptionNumber.Equals(lineItem.OptionNumber));
if (lineItem.Product is null) return quote;
lineItem.ProductId = lineItem.Product.ProductId;
lineItem.Product.CustomDescription = await genericController.GetAsync<CustomDescription>(cD => cD.ProductNumber.Equals(lineItem.ProductNumber) && cD.OptionNumber.Equals(lineItem.OptionNumber));
lineItem.Quote = quote;
lineItem.QuoteId = lineItem.Quote.QuoteId;
}
return quote;
}
private static async Task<List<CustomDescription>?> SuggestCustomDescriptions(LineItem lineItem) {
//IList<CustomDescription>? fromProductNumber = await genericController.GetAllAsync<CustomDescription>(cD => cD.ProductNumber.Equals(lineItem.ProductNumber, StringComparison.Ordinal));
IList<CustomDescription>? fromOptionNumber = new List<CustomDescription>();
if (lineItem.OptionNumber != "")
fromOptionNumber = await genericController.GetAllAsync<CustomDescription>(cD => cD.OptionNumber.Equals(lineItem.OptionNumber, StringComparison.Ordinal));
//if (fromOptionNumber == null && fromProductNumber == null) return null;
//if (fromOptionNumber == null) return fromProductNumber.ToList();
//if (fromProductNumber == null) return fromOptionNumber.ToList();
//return fromProductNumber.Union(fromOptionNumber).ToList();
return fromOptionNumber.ToList();
}
}