Gremlin/Gremlin_BlazorServer/Services/GenericImporter.cs

162 lines
8.4 KiB
C#

using Blazorise;
using Gremlin_BlazorServer.Data.EntityClasses;
using MySqlX.XDevAPI.Common;
namespace Gremlin_BlazorServer.Services;
public class GenericImporter {
public static async Task ImportCsvAsync<T>(string fileContent) where T : class, IMetadata {
Console.WriteLine($"GENERIC IMPORTER: Importing {typeof(T)} from csv...");
List<string[]> splitLines = await Task.Run(() => SplitLines(fileContent));
Console.WriteLine($"Found {splitLines.Count} potential {typeof(T)} in csv.");
await ParseLinesToResultSet<T>(splitLines);
Console.WriteLine($"GENERIC IMPORTER: Ready!");
}
private static List<string[]> SplitLines(string fileContent) {
IEnumerable<string> fileLines = fileContent.Split(Environment.NewLine.ToCharArray());
List<string[]> fileList = (from clipboardLine in fileLines where clipboardLine != "" select clipboardLine.Split('\t')).ToList();
return fileList;
}
private static async Task ParseLinesToResultSet<T>(IEnumerable<string[]> lineList) where T : class, IMetadata
{
Result<T>? result = null;
foreach (string[] line in lineList.Select(strings => strings.Select(x => x.Replace("\"", string.Empty)).ToArray())) { // Delete all ""
if (typeof(T) == typeof(Account)) result = await ParseToAccount(line) as Result<T>;
if (typeof(T) == typeof(Contact)) result = await ParseToContact(line) as Result<T>;
if (result is null) continue;
if (result.NewItem is not null) await GenericController.InsertAsync(result.NewItem);
if (result.UpdatedItem is not null) await GenericController.UpdateAsync(result.UpdatedItem);
}
}
private static async Task<Result<Account>?> ParseToAccount(IReadOnlyList<string> line) { // "ID" "Name" "Street" "City" "BP Role" "Postal Code" "Customer Type" "Market Indicator" "Phone" "E-Mail" "Market code"
if (line[0].Contains("ID")) return null; //HACK: skip first row if header
if (!uint.TryParse(line[0], out uint sapAccountNumber)) return null; //HACK: skip wrong SapAccountNumbers
if (!uint.TryParse(line[5], out uint zip)) return null; //HACK: skip wrong ZIPs
Result<Account> result = new();
string accountTypeCode = line[6];
if (accountTypeCode is "" or null) accountTypeCode = "FPC"; // standard AccountType
string subMarketCode = line[7];
if (subMarketCode is "" or null) subMarketCode = "CCH"; // standard AccountType
Account readAccount = new() {
SapAccountNumber = sapAccountNumber,
AccountName = line[1], //System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(line[1].ToLower())
Street = line[2],
City = System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(line[3].ToLower()), //line[3].ToUpper().First() + line[3][1..].ToLower(),
Zip = zip,
PhoneNumber = line[8],
EMail = line[9],
DataModificationByUser = "Gremlin Generic Importer",
AccountTypeCode = accountTypeCode,
SubMarketCode = subMarketCode
};
Account? existingAccount = GenericController.Get<Account>(a => a.SapAccountNumber == sapAccountNumber
|| a.AccountName == readAccount.AccountName);
if (existingAccount is not null) {
if (IsEqualAccount(readAccount, existingAccount)) return null;
existingAccount.DataModificationDate = DateTime.Now;
existingAccount.DataVersionNumber++;
existingAccount.DataModificationByUser = "Updated by Gremlin Generic Importer";
existingAccount.AccountName = readAccount.AccountName;
existingAccount.City = readAccount.City;
existingAccount.EMail = readAccount.EMail;
existingAccount.PhoneNumber = readAccount.PhoneNumber;
existingAccount.Street = readAccount.Street;
existingAccount.Zip = readAccount.Zip;
Console.WriteLine($"Update in Account {existingAccount.SapAccountNumber}:{existingAccount.AccountName}");
result.UpdatedItem = existingAccount;
}
else {
Console.WriteLine($"Account {readAccount.SapAccountNumber}:{readAccount.AccountName} ist neu!");
result.NewItem = readAccount;
}
return result;
}
private static async Task<Result<Contact>?> ParseToContact(IReadOnlyList<string> line) { //"Contact ID" "Account ID" "Last Name" "First Name" "Acct Name 1 and 2" "Street - Work Address" "Postal Code - Work Address" "City - Work Address" "E-Mail" "Phone" "E-Mail Opt"
if (line[0].Contains("ID")) return null; //HACK: skip first row if header
if (!uint.TryParse(line[0], out uint sapContactNumber)) return null; //HACK: skip wrong SapContactNumbers
if (!uint.TryParse(line[1], out uint sapAccountNumber)) return null; //HACK: skip wrong SapAccountNumbers
Account? account = GenericController.Get<Account>(a => a.SapAccountNumber.Equals(sapAccountNumber));
if (account is null) {
Console.WriteLine($"Account with SapAccountNumber {sapAccountNumber} is not existing!!");
return null; //HACK: skip empty Accounts
}
Result<Contact> result = new();
Contact readContact = new() {
SapContactNumber = sapContactNumber,
AccountId = account.AccountId,
LastName = System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(line[2].ToLower()),
FirstName = System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(line[3].ToLower()),
EMail = line[8].ToLower(),
EmailBounced = line[8].Contains("bounced"),
PhoneNumber = line[9],
OptInStatus = line[10] == "Opt In",
DataModificationByUser = "Gremlin Generic Importer",
Gender = 0
};
Contact? existingContact = GenericController.Get<Contact>(a => a.SapContactNumber == sapContactNumber
|| (a.LastName == readContact.LastName && a.FirstName == readContact.FirstName));
if (existingContact is not null) {
if (IsEqualContact(readContact, existingContact)) {
Console.WriteLine($"---> The contact {readContact.SapContactNumber}:{readContact.FirstName} {readContact.LastName} ist aktuell.");
return null;
}
existingContact.DataModificationDate = DateTime.Now;
existingContact.DataVersionNumber++;
existingContact.DataModificationByUser = "Updated by Gremlin Generic Importer";
existingContact.AccountId = readContact.AccountId;
existingContact.LastName = readContact.LastName;
existingContact.EMail = readContact.EMail;
existingContact.PhoneNumber = readContact.PhoneNumber;
existingContact.EmailBounced = readContact.EmailBounced;
existingContact.OptInStatus = readContact.OptInStatus;
Console.WriteLine($"Update in Contact {existingContact.SapContactNumber}:{existingContact.FirstName} {existingContact.LastName}");
result.UpdatedItem = existingContact;
}
else {
Console.WriteLine($"Contact {readContact.SapContactNumber}:{readContact.FirstName} {readContact.LastName} ist neu!");
result.NewItem = readContact;
}
return result;
}
private static bool IsEqualAccount(Account account, Account existingAccount)
=> account.AccountName == existingAccount.AccountName
&& account.City == existingAccount.City
&& account.EMail == existingAccount.EMail
&& account.PhoneNumber == existingAccount.PhoneNumber
&& account.Street == existingAccount.Street
&& account.Zip == existingAccount.Zip;
private static bool IsEqualContact(Contact contact, Contact existingContact)
=> contact.LastName == existingContact.LastName
&& contact.FirstName == existingContact.FirstName
&& contact.EMail == existingContact.EMail
&& contact.PhoneNumber == existingContact.PhoneNumber
&& contact.EmailBounced == existingContact.EmailBounced
&& contact.OptInStatus == existingContact.OptInStatus;
}
internal class Result<T> {
public T? NewItem { get; set; }
public T? UpdatedItem { get; set; }
}