220 lines
9.9 KiB
C#
220 lines
9.9 KiB
C#
using System.Globalization;
|
|
using System.Text;
|
|
using Gremlin_BlazorServer.Data.EntityClasses;
|
|
using Gremlin_BlazorServer.Pages.Quotes;
|
|
using NuGet.Packaging;
|
|
|
|
namespace Gremlin_BlazorServer.Services;
|
|
|
|
public class QuoteHandling {
|
|
// private static readonly GenericController genericController = new();
|
|
|
|
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 static Quote ReadLineItems(Quote quote, Contact recipient, string clipboard) {
|
|
try {
|
|
quote = ResetTotals(quote);
|
|
|
|
quote.LineItems = ReadLineItemsFromClipboard(quote, 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 (recipient.Account.AccountName is not null) quote.ValidFor = CheckForAcademic(recipient.Account);
|
|
|
|
foreach (LineItem lineItem in quote.LineItems) {
|
|
if (lineItem.OptionNumber is null or "") 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 static List<LineItem> ReadLineItemsFromClipboard(Quote quote, 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(quote, clipboardList).Result;
|
|
return lineItems;
|
|
}
|
|
|
|
private static Task<List<LineItem>> ParseClipboardList(Quote quote, 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),
|
|
QuoteId = quote.QuoteId
|
|
};
|
|
|
|
lineItems.Add(lineItem);
|
|
}
|
|
else {
|
|
Console.WriteLine("Angebot konnte nicht eingelesen werden!");
|
|
}
|
|
|
|
return Task.FromResult(lineItems);
|
|
}
|
|
|
|
private static byte CheckForAcademic(Account account) {
|
|
return account.AccountType?.AccountTypeCode == null ? (byte)60 : (byte)(account.AccountType.AccountTypeCode.StartsWith("N") ? 90 : 60);
|
|
}
|
|
|
|
private static decimal GetFreight(decimal net, decimal freight) {
|
|
decimal freightNet = net * freight / 100;
|
|
return freightNet < 3000 ? freightNet : 3000;
|
|
}
|
|
|
|
private static 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 static 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 static decimal GetTotal(Quote quote, string type) {
|
|
decimal total = 0;
|
|
if (quote.LineItems.Count == 0) 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 static 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 static async Task<Quote> GenerateQuoteFromString(Quote quote, Contact recipient, string fileContent) {
|
|
quote = ReadLineItems(quote, recipient, fileContent);
|
|
if (recipient.Account.AccountName is not null) quote.Path = HostingService.GetPath(quote, recipient) ?? "Path not found!";
|
|
if (quote.LineItems is null || quote.LineItems.Count == 0) return quote;
|
|
|
|
FileService.WriteQuoteToTsv(fileContent, quote);
|
|
|
|
//TODO Load all relevant CustomDescriptions upfront
|
|
foreach (LineItem lineItem in quote.LineItems) {
|
|
CustomDescription? newCustomDescription = GenericController.Get<CustomDescription>(newCustomDescription => newCustomDescription.ProductNumber.Equals(lineItem.ProductNumber, StringComparison.Ordinal) && newCustomDescription.OptionNumber!.Equals(lineItem.OptionNumber, StringComparison.Ordinal));
|
|
if (newCustomDescription is null) continue;
|
|
if (lineItem.ProductNumber is null) continue;
|
|
if (newCustomDescription.DescriptionText 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);
|
|
}
|
|
|
|
// Product product = await GenericController.GetAsync<Product>(p => p.ProductNumber.Equals(lineItem.ProductNumber) && p.OptionNumber.Equals(lineItem.OptionNumber));
|
|
// lineItem.ProductId = product.ProductId;
|
|
CustomDescription? customDescription = GenericController.Get<CustomDescription>(cD => cD.ProductNumber.Equals(lineItem.ProductNumber) && cD.OptionNumber.Equals(lineItem.OptionNumber));
|
|
if (customDescription is not null) lineItem.CustomDescriptionId = customDescription.CustomDescriptionId;
|
|
// lineItem.QuoteId = quote.QuoteId;
|
|
}
|
|
|
|
return quote;
|
|
}
|
|
|
|
private static async Task<List<CustomDescription>> SuggestCustomDescriptions(LineItem lineItem) {
|
|
IList<CustomDescription> suggestions = new List<CustomDescription>();
|
|
if (lineItem.ProductNumber is not null)
|
|
suggestions.AddRange(await GenericController.GetAllAsync<CustomDescription>(cD => cD.ProductNumber!.Equals(lineItem.ProductNumber, StringComparison.Ordinal)));
|
|
if (lineItem.OptionNumber is not null)
|
|
suggestions.AddRange(await GenericController.GetAllAsync<CustomDescription>(cD => cD.OptionNumber!.Equals(lineItem.OptionNumber, StringComparison.Ordinal)));
|
|
return suggestions.ToList();
|
|
}
|
|
} |