Import of Contacts

pull/3/head
Sascha Woitschetzki 2023-08-14 13:28:15 +07:00
parent 79a2dc545a
commit d70383bbc1
8 changed files with 98 additions and 72 deletions

@ -45,7 +45,7 @@ public partial class Accounts {
_ = stream.Seek(0, SeekOrigin.Begin); _ = stream.Seek(0, SeekOrigin.Begin);
using StreamReader reader = new(stream); using StreamReader reader = new(stream);
string fileContent = await reader.ReadToEndAsync(); string fileContent = await reader.ReadToEndAsync();
await GenericImporter.ImportCsvAsync<Account>(fileContent); GenericImporter.ImportCsv<Account>(fileContent);
} }
} }
catch (Exception exception) { catch (Exception exception) {
@ -55,19 +55,21 @@ public partial class Accounts {
StateHasChanged(); StateHasChanged();
} }
private static async Task OnRowInsertedAsync(SavedRowItem<Account, Dictionary<string, object>> account) { private static Task OnRowInsertedAsync(SavedRowItem<Account, Dictionary<string, object>> account) {
Account newAccount = ResolveAccountAsync(account.Item); Account newAccount = ResolveAccountAsync(account.Item);
// if (newAccount.AccountType is null || newAccount.SubMarket is null) return; // if (newAccount.AccountType is null || newAccount.SubMarket is null) return;
int count = await GenericController.InsertAsync(newAccount); int count = GenericController.Insert(newAccount);
Console.WriteLine($"Inserted {count} properties for new account {newAccount.AccountId}: {newAccount.AccountName}."); Console.WriteLine($"Inserted {count} properties for new account {newAccount.AccountId}: {newAccount.AccountName}.");
return Task.CompletedTask;
} }
private static async Task OnRowUpdatedAsync(SavedRowItem<Account, Dictionary<string, object>> account) { private static Task OnRowUpdatedAsync(SavedRowItem<Account, Dictionary<string, object>> account) {
Account newAccount = ResolveAccountAsync(account.Item); Account newAccount = ResolveAccountAsync(account.Item);
if (newAccount.AccountType == null || newAccount.SubMarket == null) if (newAccount.AccountType == null || newAccount.SubMarket == null)
return; return Task.CompletedTask;
int count = await GenericController.UpdateAsync(account.Item); int count = GenericController.Update(account.Item);
Console.WriteLine($"Updated {count} properties in account {newAccount.AccountId}: {newAccount.AccountName}."); Console.WriteLine($"Updated {count} properties in account {newAccount.AccountId}: {newAccount.AccountName}.");
return Task.CompletedTask;
} }
private static async Task OnRowRemovedAsync(Account account) { private static async Task OnRowRemovedAsync(Account account) {

@ -38,14 +38,14 @@ public partial class Contacts {
private async Task OnRowInsertedAsync(SavedRowItem<Contact, Dictionary<string, object>> contact) { private async Task OnRowInsertedAsync(SavedRowItem<Contact, Dictionary<string, object>> contact) {
Contact newContact = await ResolveContactAsync(contact.Item); Contact newContact = await ResolveContactAsync(contact.Item);
// if (newContact.Account is null) return; // if (newContact.Account is null) return;
int count = await GenericController.InsertAsync(newContact); int count = GenericController.Insert(newContact);
Console.WriteLine($"Inserted {count} properties for new contact {newContact.ContactId}: {newContact.FirstName} {newContact.LastName}."); Console.WriteLine($"Inserted {count} properties for new contact {newContact.ContactId}: {newContact.FirstName} {newContact.LastName}.");
} }
private async Task OnRowUpdatedAsync(SavedRowItem<Contact, Dictionary<string, object>> contact) { private async Task OnRowUpdatedAsync(SavedRowItem<Contact, Dictionary<string, object>> contact) {
Contact newContact = await ResolveContactAsync(contact.Item); Contact newContact = await ResolveContactAsync(contact.Item);
// if (newContact.Account is null) return; // if (newContact.Account is null) return;
int count = await GenericController.UpdateAsync(contact.Item); int count = GenericController.Update(contact.Item);
Console.WriteLine($"Updated {count} properties in contact {newContact.ContactId}: {newContact.FirstName} {newContact.LastName}."); Console.WriteLine($"Updated {count} properties in contact {newContact.ContactId}: {newContact.FirstName} {newContact.LastName}.");
} }
@ -80,7 +80,7 @@ public partial class Contacts {
_ = stream.Seek(0, SeekOrigin.Begin); _ = stream.Seek(0, SeekOrigin.Begin);
using StreamReader reader = new(stream); using StreamReader reader = new(stream);
string fileContent = await reader.ReadToEndAsync(); string fileContent = await reader.ReadToEndAsync();
await GenericImporter.ImportCsvAsync<Contact>(fileContent); GenericImporter.ImportCsv<Contact>(fileContent);
} }
} }
catch (Exception exception) { catch (Exception exception) {

@ -34,7 +34,7 @@ public partial class CustomDescriptions {
_ = stream.Seek(0, SeekOrigin.Begin); _ = stream.Seek(0, SeekOrigin.Begin);
using StreamReader reader = new(stream); using StreamReader reader = new(stream);
string fileContent = await reader.ReadToEndAsync(); string fileContent = await reader.ReadToEndAsync();
await GenericImporter.ImportCsvAsync<CustomDescription>(fileContent); GenericImporter.ImportCsv<CustomDescription>(fileContent);
} }
} }
catch (Exception exception) { catch (Exception exception) {
@ -43,16 +43,18 @@ public partial class CustomDescriptions {
StateHasChanged(); StateHasChanged();
} }
private static async Task OnRowInsertedAsync(SavedRowItem<CustomDescription, Dictionary<string, object>> customDescription) { private static Task OnRowInsertedAsync(SavedRowItem<CustomDescription, Dictionary<string, object>> customDescription) {
CustomDescription newCustomDescription = ResolveCustomDescriptionAsync(customDescription.Item); CustomDescription newCustomDescription = ResolveCustomDescriptionAsync(customDescription.Item);
int count = await GenericController.InsertAsync(newCustomDescription); int count = GenericController.Insert(newCustomDescription);
Console.WriteLine($"Inserted {count} properties for new custom description {newCustomDescription.ProductNumber}#{newCustomDescription.OptionNumber}: {newCustomDescription.Heading}"); Console.WriteLine($"Inserted {count} properties for new custom description {newCustomDescription.ProductNumber}#{newCustomDescription.OptionNumber}: {newCustomDescription.Heading}");
return Task.CompletedTask;
} }
private static async Task OnRowUpdatedAsync(SavedRowItem<CustomDescription, Dictionary<string, object>> customDescription) { private static Task OnRowUpdatedAsync(SavedRowItem<CustomDescription, Dictionary<string, object>> customDescription) {
CustomDescription newCustomDescription = ResolveCustomDescriptionAsync(customDescription.Item); CustomDescription newCustomDescription = ResolveCustomDescriptionAsync(customDescription.Item);
int count = await GenericController.UpdateAsync(customDescription.Item); int count = GenericController.Update(customDescription.Item);
Console.WriteLine($"Updated {count} properties for custom description {newCustomDescription.ProductNumber}#{newCustomDescription.OptionNumber}: {newCustomDescription.Heading}"); Console.WriteLine($"Updated {count} properties for custom description {newCustomDescription.ProductNumber}#{newCustomDescription.OptionNumber}: {newCustomDescription.Heading}");
return Task.CompletedTask;
} }
private static async Task OnRowRemovedAsync(CustomDescription customDescription) { private static async Task OnRowRemovedAsync(CustomDescription customDescription) {

@ -36,13 +36,13 @@ public partial class ProductLines {
private async Task OnRowInsertedAsync(SavedRowItem<ProductLine, Dictionary<string, object>> productLine) { private async Task OnRowInsertedAsync(SavedRowItem<ProductLine, Dictionary<string, object>> productLine) {
ProductLine newProductLine = await ResolveProductAsync(productLine.Item); ProductLine newProductLine = await ResolveProductAsync(productLine.Item);
int count = await GenericController.InsertAsync(newProductLine); int count = GenericController.Insert(newProductLine);
Console.WriteLine($"Inserted {count} properties for new ProductLine {newProductLine.ProductLineCode}."); Console.WriteLine($"Inserted {count} properties for new ProductLine {newProductLine.ProductLineCode}.");
} }
private async Task OnRowUpdatedAsync(SavedRowItem<ProductLine, Dictionary<string, object>> productLine) { private async Task OnRowUpdatedAsync(SavedRowItem<ProductLine, Dictionary<string, object>> productLine) {
ProductLine newProductLine = await ResolveProductAsync(productLine.Item); ProductLine newProductLine = await ResolveProductAsync(productLine.Item);
int count = await GenericController.UpdateAsync(productLine.Item); int count = GenericController.Update(productLine.Item);
Console.WriteLine($"Updated {count} properties in ProductLine {newProductLine.ProductLineCode}."); Console.WriteLine($"Updated {count} properties in ProductLine {newProductLine.ProductLineCode}.");
} }

@ -221,7 +221,7 @@ public partial class QuoteAdd {
//TODO need to wait for modal! //TODO need to wait for modal!
//Insert new CustomDescription to db //Insert new CustomDescription to db
int count = await GenericController.InsertAsync(newCustomDescription); int count = GenericController.Insert(newCustomDescription);
Console.WriteLine($"Inserted {count} new CustomDescriptions"); Console.WriteLine($"Inserted {count} new CustomDescriptions");
// Product product = await GenericController.GetAsync<Product>(p => p.ProductNumber.Equals(lineItem.ProductNumber) && p.OptionNumber.Equals(lineItem.OptionNumber)); // Product product = await GenericController.GetAsync<Product>(p => p.ProductNumber.Equals(lineItem.ProductNumber) && p.OptionNumber.Equals(lineItem.OptionNumber));
@ -308,13 +308,14 @@ public partial class QuoteAdd {
if (quote is { LineItems: not null, Recipient.Account: not null }) lineItemsNotReady = false; if (quote is { LineItems: not null, Recipient.Account: not null }) lineItemsNotReady = false;
} }
private async Task OnSave() { private Task OnSave() {
if (await GenericController.InsertAsync(quote) > 0) { if (GenericController.Insert(quote) <= 0) return Task.CompletedTask;
// if (await GenericController.InsertAsync(quote.LineItems) > 0) { // if (await GenericController.InsertAsync(quote.LineItems) > 0) {
Console.WriteLine($"Succesfully added quote {quote.QuotationNumber} to db with {quote.LineItems.Count} lineitems and a total net of {quote.TotalNet} euros."); Console.WriteLine($"Succesfully added quote {quote.QuotationNumber} to db with {quote.LineItems.Count} lineitems and a total net of {quote.TotalNet} euros.");
NavigationManager.NavigateTo("Quotes/QuoteIndex"); NavigationManager.NavigateTo("Quotes/QuoteIndex");
// } // }
}
return Task.CompletedTask;
} }
private async Task OnCreateTex() { private async Task OnCreateTex() {
@ -383,16 +384,18 @@ public partial class QuoteAdd {
isReloadingLineItems = false; isReloadingLineItems = false;
} }
private static async Task OnRowInsertedAsync(SavedRowItem<CustomDescription, Dictionary<string, object>> customDescription) { private static Task OnRowInsertedAsync(SavedRowItem<CustomDescription, Dictionary<string, object>> customDescription) {
CustomDescription nCd = ResolveCustomDescription(customDescription.Item); CustomDescription nCd = ResolveCustomDescription(customDescription.Item);
int count = await GenericController.InsertAsync(nCd); int count = GenericController.Insert(nCd);
Console.WriteLine($"Inserted {count} properties for new custom description {nCd.ProductNumber}#{nCd.OptionNumber}: {nCd.Heading}"); Console.WriteLine($"Inserted {count} properties for new custom description {nCd.ProductNumber}#{nCd.OptionNumber}: {nCd.Heading}");
return Task.CompletedTask;
} }
private static async Task OnRowUpdatedAsync(SavedRowItem<CustomDescription, Dictionary<string, object>> customDescription) { private static Task OnRowUpdatedAsync(SavedRowItem<CustomDescription, Dictionary<string, object>> customDescription) {
CustomDescription nCd = ResolveCustomDescription(customDescription.Item); CustomDescription nCd = ResolveCustomDescription(customDescription.Item);
int count = await GenericController.UpdateAsync(customDescription.Item); int count = GenericController.Update(customDescription.Item);
Console.WriteLine($"Updated {count} properties for custom description {nCd.ProductNumber}#{nCd.OptionNumber}: {nCd.Heading}"); Console.WriteLine($"Updated {count} properties for custom description {nCd.ProductNumber}#{nCd.OptionNumber}: {nCd.Heading}");
return Task.CompletedTask;
} }
private static async Task OnRowRemovedAsync(CustomDescription customDescription) { private static async Task OnRowRemovedAsync(CustomDescription customDescription) {

@ -125,10 +125,10 @@ public class GenericController {
} }
} }
public static async Task<int> InsertAsync<T>(T entity) where T : class, IMetadata { public static int Insert<T>(T entity) where T : class, IMetadata {
try { try {
gremlinDb.Set<T>().Add(entity); gremlinDb.Set<T>().Add(entity);
return await gremlinDb.SaveChangesAsync(); return gremlinDb.SaveChanges();
} }
catch (DbUpdateException ex) { catch (DbUpdateException ex) {
Console.WriteLine($"{ex.InnerException}"); Console.WriteLine($"{ex.InnerException}");
@ -141,11 +141,11 @@ public class GenericController {
} }
} }
public static async Task<int> InsertAsync<T>(IEnumerable<T> entities) where T : class, IMetadata { public static int Insert<T>(IEnumerable<T> entities) where T : class, IMetadata {
// gremlinDb.Set<T>().ToList(); //Get newest versions fresh from db // gremlinDb.Set<T>().ToList(); //Get newest versions fresh from db
try { try {
gremlinDb.Set<T>().AddRange(entities); gremlinDb.Set<T>().AddRange(entities);
return await gremlinDb.SaveChangesAsync(); return gremlinDb.SaveChanges();
} }
catch (DbUpdateException ex) { catch (DbUpdateException ex) {
HandleConcurrencyExceptions(ex); HandleConcurrencyExceptions(ex);
@ -167,11 +167,10 @@ public class GenericController {
} }
} }
public static async Task<int> UpdateAsync<T>(T entity) where T : class, IMetadata { public static int Update<T>(T entity) where T : class, IMetadata {
Task<T?> task = gremlinDb.Set<T>().FirstOrDefaultAsync(t => t.Equals(entity)); //Get newest version fresh from db
try { try {
gremlinDb.Set<T>().Update(entity); gremlinDb.Set<T>().Update(entity);
return await gremlinDb.SaveChangesAsync(false); return gremlinDb.SaveChanges(false);
} }
catch (DbUpdateException ex) { catch (DbUpdateException ex) {
HandleConcurrencyExceptions(ex); HandleConcurrencyExceptions(ex);
@ -183,12 +182,10 @@ public class GenericController {
} }
} }
public static async Task<int> UpdateAsync<T>(IEnumerable<T> entities) where T : class, IMetadata { public static int Update<T>(IEnumerable<T> entities) where T : class, IMetadata {
// IQueryable<T> list = gremlinDb.Set<T>().Where(t => t.Equals(entities)); //Get newest version fresh from db
try { try {
await Task.Run(() => gremlinDb.Set<T>().UpdateRange(entities)); gremlinDb.Set<T>().UpdateRange(entities);
return await gremlinDb.SaveChangesAsync(); return gremlinDb.SaveChanges();
} }
catch (DbUpdateException ex) { catch (DbUpdateException ex) {
HandleConcurrencyExceptions(ex); HandleConcurrencyExceptions(ex);

@ -7,12 +7,11 @@ namespace Gremlin_BlazorServer.Services;
public class GenericImporter { public class GenericImporter {
public static async Task ImportCsvAsync<T>(string fileContent) where T : class, IMetadata, new() { public static void ImportCsv<T>(string fileContent) where T : class, IMetadata, new() {
Console.WriteLine($"GENERIC IMPORTER: Importing {typeof(T)} from csv..."); Console.WriteLine($"GENERIC IMPORTER: Importing {typeof(T)} from csv...");
List<string[]> splitLines = await Task.Run(() => SplitLines(fileContent)); List<string[]> splitLines = SplitLines(fileContent);
Console.WriteLine($"Found {splitLines.Count} potential {typeof(T)} in csv."); Console.WriteLine($"Found {splitLines.Count} potential {typeof(T)} in csv.");
ParseLinesToResultSet<T>(splitLines); Console.WriteLine(ParseLinesToResultSet<T>(splitLines) ? $"GENERIC IMPORTER: Ready." : $"GENERIC IMPORTER: Error by writing to db!");
Console.WriteLine($"GENERIC IMPORTER: Ready!");
} }
private static List<string[]> SplitLines(string fileContent) { private static List<string[]> SplitLines(string fileContent) {
@ -21,7 +20,7 @@ public class GenericImporter {
return fileList; return fileList;
} }
private static async void ParseLinesToResultSet<T>(IEnumerable<string[]> lineList) where T : class, IMetadata, new() { private static bool ParseLinesToResultSet<T>(IEnumerable<string[]> lineList) where T : class, IMetadata, new() {
Tuple<T?, T?>? resultSet = new(new(), new()); Tuple<T?, T?>? resultSet = new(new(), new());
List<T> updatedItems = new(); List<T> updatedItems = new();
List<T> newItems = new(); List<T> newItems = new();
@ -35,9 +34,12 @@ public class GenericImporter {
if (resultSet.Item2 is not null) newItems.Add(resultSet.Item2); if (resultSet.Item2 is not null) newItems.Add(resultSet.Item2);
} }
int success = 0;
Console.WriteLine($"Found {updatedItems.Count} updates and {newItems.Count} new items."); Console.WriteLine($"Found {updatedItems.Count} updates and {newItems.Count} new items.");
if (updatedItems.Count > 0) await GenericController.UpdateAsync(updatedItems); if (updatedItems.Count > 0) success += GenericController.Update(updatedItems);
if (newItems.Count > 0) await GenericController.InsertAsync(newItems); if (newItems.Count > 0) success += GenericController.Insert(newItems);
return success > 0;
} }
private static Tuple<Account?, Account?>? ParseToAccount(IReadOnlyList<string> line) { // "ID" "Name" "Street" "City" "BP Role" "Postal Code" "Customer Type" "Market Indicator" "Phone" "E-Mail" "Market code" private static Tuple<Account?, Account?>? ParseToAccount(IReadOnlyList<string> line) { // "ID" "Name" "Street" "City" "BP Role" "Postal Code" "Customer Type" "Market Indicator" "Phone" "E-Mail" "Market code"
@ -81,7 +83,6 @@ public class GenericImporter {
existingAccount.PhoneNumber = readAccount.PhoneNumber; existingAccount.PhoneNumber = readAccount.PhoneNumber;
existingAccount.Street = readAccount.Street; existingAccount.Street = readAccount.Street;
existingAccount.Zip = readAccount.Zip; existingAccount.Zip = readAccount.Zip;
Console.WriteLine($"Update in Account {existingAccount.SapAccountNumber}:{existingAccount.AccountName}");
updatedAccount = existingAccount; updatedAccount = existingAccount;
} }
else { else {
@ -119,12 +120,11 @@ public class GenericImporter {
Gender = 0 Gender = 0
}; };
Contact? existingContact = GenericController.Get<Contact>(a => a.SapContactNumber == sapContactNumber Contact? existingContact = GenericController.Get<Contact>(a => a.SapContactNumber == sapContactNumber || (a.LastName == readContact.LastName && a.FirstName == readContact.FirstName));
|| (a.LastName == readContact.LastName && a.FirstName == readContact.FirstName));
if (existingContact is not null) { if (existingContact is not null) {
if (IsEqualContact(readContact, existingContact)) { if (IsEqualContact(readContact, existingContact)) {
Console.WriteLine($"---> The contact {readContact.SapContactNumber}:{readContact.FirstName} {readContact.LastName} ist aktuell."); // Console.WriteLine($"---> The contact {readContact.SapContactNumber}:{readContact.FirstName} {readContact.LastName} ist aktuell.");
return null; return null;
} }
@ -148,24 +148,46 @@ public class GenericImporter {
return new(updatedContact, newContact); return new(updatedContact, newContact);
} }
private static bool IsEqualAccount(Account account, Account existingAccount) private static bool IsEqualAccount(Account readAccount, Account existingAccount) {
=> account.AccountName == existingAccount.AccountName bool equalAccount = true;
&& account.City == existingAccount.City if (readAccount.AccountName != existingAccount.AccountName) {
&& account.EMail == existingAccount.EMail equalAccount = false;
&& account.PhoneNumber == existingAccount.PhoneNumber Console.WriteLine($"--- UPDATE in Account {readAccount.SapAccountNumber} ---");
&& account.Street == existingAccount.Street Console.WriteLine($"{readAccount.AccountName} | {existingAccount.AccountName}");
&& account.Zip == existingAccount.Zip; }
if (readAccount.City != existingAccount.City) {
private static bool IsEqualContact(Contact contact, Contact existingContact) equalAccount = false;
=> contact.LastName == existingContact.LastName Console.WriteLine($"--- UPDATE in Account {readAccount.SapAccountNumber} ---");
&& contact.FirstName == existingContact.FirstName Console.WriteLine($"{readAccount.City} | {existingAccount.City}");
&& contact.EMail == existingContact.EMail }
&& contact.PhoneNumber == existingContact.PhoneNumber if (readAccount.EMail != existingAccount.EMail) {
&& contact.EmailBounced == existingContact.EmailBounced equalAccount = false;
&& contact.OptInStatus == existingContact.OptInStatus; Console.WriteLine($"--- UPDATE in Account {readAccount.SapAccountNumber} ---");
Console.WriteLine($"{readAccount.EMail} | {existingAccount.EMail}");
}
if (readAccount.PhoneNumber != existingAccount.PhoneNumber) {
equalAccount = false;
Console.WriteLine($"--- UPDATE in Account {readAccount.SapAccountNumber} ---");
Console.WriteLine($"{readAccount.PhoneNumber} | {existingAccount.PhoneNumber}");
}
if (readAccount.Street != existingAccount.Street) {
equalAccount = false;
Console.WriteLine($"--- UPDATE in Account {readAccount.SapAccountNumber} ---");
Console.WriteLine($"{readAccount.Street} | {existingAccount.Street}");
}
if (readAccount.Zip != existingAccount.Zip) {
equalAccount = false;
Console.WriteLine($"--- UPDATE in Account {readAccount.SapAccountNumber} ---");
Console.WriteLine($"{readAccount.Zip} | {existingAccount.Zip}");
}
return equalAccount;
} }
internal class Result<T> { private static bool IsEqualContact(Contact readContact, Contact existingContact)
public T? NewItem { get; set; } => readContact.LastName == existingContact.LastName
public T? UpdatedItem { get; set; } && readContact.FirstName == existingContact.FirstName
&& readContact.EMail == existingContact.EMail
&& readContact.PhoneNumber == existingContact.PhoneNumber
&& readContact.EmailBounced == existingContact.EmailBounced
&& readContact.OptInStatus == existingContact.OptInStatus;
} }

@ -206,7 +206,7 @@ public class QuoteHandling {
AccountId = 1 AccountId = 1
}; };
int count = await GenericController.InsertAsync(newCustomDescription); int count = GenericController.Insert(newCustomDescription);
Console.WriteLine($"Inserted {count} new CustomDescriptions"); Console.WriteLine($"Inserted {count} new CustomDescriptions");
// Product product = await GenericController.GetAsync<Product>(p => p.ProductNumber.Equals(lineItem.ProductNumber) && p.OptionNumber.Equals(lineItem.OptionNumber)); // Product product = await GenericController.GetAsync<Product>(p => p.ProductNumber.Equals(lineItem.ProductNumber) && p.OptionNumber.Equals(lineItem.OptionNumber));