1609 lines
73 KiB
C#
1609 lines
73 KiB
C#
using System.Data;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
using System.Text;
|
|
using Gremlin_BlazorServer.Data.EntityClasses;
|
|
using Gremlin_BlazorServer.Services;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.VisualBasic.FileIO;
|
|
using MySqlConnector;
|
|
using static Gremlin_BlazorServer.Data.EntityClasses.Enums;
|
|
|
|
namespace Gremlin_BlazorServer.Data.DBClasses;
|
|
|
|
internal static class DbHelper {
|
|
private static readonly DateTime farInTheFuture = DateTime.Parse("2050-12-31t00:00:00.000000z", CultureInfo.CurrentCulture);
|
|
private static readonly ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = Environment.ProcessorCount * 4 };
|
|
private static readonly Random random = new();
|
|
|
|
public static bool CheckDatabaseConnection(string connectionString) {
|
|
bool isConnected = false;
|
|
MySqlConnection mySqlConnection = new();
|
|
|
|
try {
|
|
mySqlConnection = new(connectionString);
|
|
mySqlConnection.Open();
|
|
isConnected = true;
|
|
}
|
|
|
|
catch (ArgumentException aEx) {
|
|
Console.WriteLine(aEx.Message);
|
|
}
|
|
|
|
catch (MySqlException ex) {
|
|
Console.WriteLine($"Message: {ex.Message}\nSource: {ex.Source}\nNumber: {ex.Number}", "Connection Failed!");
|
|
|
|
isConnected = false;
|
|
|
|
switch (ex.Number) {
|
|
case 1042: // Unable to connect to any of the specified MySQL hosts (Check Server,Port)
|
|
break;
|
|
case 0: // Access denied (Check DB name,username,password)
|
|
break;
|
|
}
|
|
}
|
|
|
|
finally {
|
|
if (mySqlConnection.State == ConnectionState.Open) mySqlConnection.Close();
|
|
}
|
|
|
|
return isConnected;
|
|
}
|
|
|
|
public static void DbBuilder() {
|
|
using GremlinDb gremlinDb = new();
|
|
_ = gremlinDb.Database.EnsureDeleted();
|
|
_ = gremlinDb.Database.EnsureCreated();
|
|
}
|
|
|
|
public static void DbInitializer() {
|
|
//PRODUCT LINES
|
|
string[] productLineAbbreviations = { "XF", "LM", "XA", "RB", "GE", "9Z", "9P", "9M", "9K", "9H", "9F", "9E", "9C", "ZZ", "ZF", "V1", "MB", "MA", "LI", "JW", "CA", "BZ", "BC", "AZ", "AJ", "AB", "AA", "8P", "89", "74", "6P", "6G", "58", "29", "AM", "RP", "CD", "PT", "XB", "RM", "GS", "AT", "SR", "FS", "BD", "UF", "3P" };
|
|
string[] productLineDescriptions = { "Cell Analysis", "Lab Management", "Flow Cell", "Remarketed Instruments", " Genomics", "Drugs of Abuse", "Sample Prep/Resins", "Research Products", "Dissolution & Other", "Vacuum Products", "AA/OES", "Drugs of Abuse", "Micro GC", "Common PL & Default", "Expedite Freight", "Automation", "Particle Analysis", "Molecular Spectroscopy", "Software and Informatics", "GC Columns", "Mid Range GC", "GC-MS", "LC Columns", "Gas Phase Analysis", "ICPMS", "Bio-consumables", "Instrument Supplies", "Analytical Parts Sup", "LC-MS", "Support Services", "Software and Professinal Services", "Other Local Products", "Competitive Supplies", "LC", "Amplicon Sequencing", "Reagent Partnership", "Companion Diagnostic", "Pathology", "Biotek", "Raman Spectroscopy", "Genomics Systems", "Parallel CE Instrument", "Bio Reagents", "Flexible Spending", "Nucleic Acid", "Microfluidics", "3rd Party Product" };
|
|
|
|
int length = productLineAbbreviations.Length;
|
|
for (int i = 0; i < length; i++) {
|
|
ProductLine plToBeAdded = new() { ProductLineCode = productLineAbbreviations[i], ProductLineDescription = productLineDescriptions[i], DataStatus = Status.Active.ToString(), DataModificationByUser = "DbInitializer" };
|
|
|
|
using (GremlinDb gremlinDb = new()) {
|
|
_ = gremlinDb.ProductLines.Add(plToBeAdded);
|
|
|
|
_ = gremlinDb.SaveChanges();
|
|
}
|
|
}
|
|
|
|
//ACCOUNT TYPES
|
|
string[] accountTypes = { "FPC", "FPR", "FPT", "FPV", "FPN", "FPP", "FPG", "FPX", "FPS", "FPA", "FPO", "FPW", "NPU", "NPR", "NPG", "NPH", "SUP" };
|
|
string[] accountTypeDescription = { "Commercial", "Contract Manufacturing CRM & Contract Research CRO", "Contract Testing", "Instrument IDR Distributor", "Instrument National Distributor", "Foreign Trade Org", "Genomics/CSD Distributor", "Regulated Distributor", "Transactional Reseller", "Value Added Reseller", "OEM", "Occasional resellers", "University", "Research Institute", "Government", "Hospital", "Supplier" };
|
|
|
|
length = accountTypes.Length;
|
|
for (int i = 0; i < length; i++) {
|
|
AccountType aTtoBeAdded = new() { AccountTypeCode = accountTypes[i], AccountTypeDescription = accountTypeDescription[i], DataStatus = Status.Active.ToString() };
|
|
_ = MetaDataSetter.ForImport(aTtoBeAdded, "DbInitializer", "DbInitializer");
|
|
|
|
using (GremlinDb gremlinDb = new()) {
|
|
_ = gremlinDb.AccountTypes.Add(aTtoBeAdded);
|
|
|
|
_ = gremlinDb.SaveChanges();
|
|
}
|
|
}
|
|
|
|
//SubMarkets
|
|
string[] subMarketCodes = { "CCH", "CEN", "CFD", "CFR", "CMS", "COT", "LPH", "LBT", "LGN", "LRS", "DCT", "LOT", "VEN", "VAR", "SUP" };
|
|
|
|
string[] subMarketDescriptions = { "Chemical & Energy", "Environmental", "Food", "Forensics", "Material Science", "CA Other", "Pharmaceutical", "BioPharma", "Generics", "LS Research", "Clinical Testing", "LS Other", "Analytical Instrument Vendor", "VAR-Partner", "Supplier" };
|
|
|
|
length = subMarketCodes.Length;
|
|
for (int i = 0; i < length; i++) {
|
|
SubMarket sMtoBeAdded = new() { SubMarketCode = subMarketCodes[i], SubMarketDescription = subMarketDescriptions[i], DataStatus = Status.Active.ToString() };
|
|
_ = MetaDataSetter.ForImport(sMtoBeAdded, "DbInitializer", "DbInitializer");
|
|
|
|
using (GremlinDb gremlinDb = new()) {
|
|
_ = gremlinDb.SubMarkets.Add(sMtoBeAdded);
|
|
|
|
_ = gremlinDb.SaveChanges();
|
|
}
|
|
}
|
|
|
|
List<Account> seedAccounts = new();
|
|
Account agilent = new() {
|
|
AccountName = "Agilent Technologies",
|
|
AccountId = 1,
|
|
Street = "Hewlett-Packard-Str. 8",
|
|
Zip = 76337,
|
|
City = "Waldbronn",
|
|
SapAccountNumber = 00000001,
|
|
EMail = "CustomerCare_Germany@agilent.com",
|
|
PhoneNumber = "+49 800 6031000",
|
|
DataStatus = Status.Active.ToString(),
|
|
AccountType = new() { AccountTypeCode = "SUP" },
|
|
SubMarket = new() { SubMarketCode = "VEN" }
|
|
};
|
|
seedAccounts.Add(agilent);
|
|
|
|
Account bios = new() {
|
|
AccountName = "Bios Analytical Ltd.",
|
|
AccountId = 2,
|
|
Street = "7 South Fens Enterprise Park//Fenton Way//PE16 6WA Chatteris//Cambridgeshire//United Kingdom",
|
|
Zip = 0,
|
|
City = "Chatteris, UNITED KINGDOM",
|
|
SapAccountNumber = 00000002,
|
|
EMail = "",
|
|
PhoneNumber = "+44 1354 694377",
|
|
DataStatus = Status.Active.ToString(),
|
|
AccountType = new() { AccountTypeCode = "SUP" },
|
|
SubMarket = new() { SubMarketCode = "VAR" }
|
|
};
|
|
seedAccounts.Add(bios);
|
|
|
|
Account huber = new() {
|
|
AccountName = "Huber Kältemaschinenbau AG",
|
|
AccountId = 3,
|
|
Street = "Werner-von-Siemens-Straße 1",
|
|
Zip = 77656,
|
|
City = "Offenburg",
|
|
SapAccountNumber = 00000003,
|
|
EMail = "sales@huber-online.com",
|
|
PhoneNumber = "0781 96030",
|
|
DataStatus = Status.Active.ToString(),
|
|
AccountType = new() { AccountTypeCode = "SUP" },
|
|
SubMarket = new() { SubMarketCode = "SUP" }
|
|
};
|
|
seedAccounts.Add(huber);
|
|
|
|
Account vanderheijden = new() {
|
|
AccountName = "Van der Heijden Labortechnik GmbH",
|
|
AccountId = 4,
|
|
Street = "Tramsmeiers Berg 2",
|
|
Zip = 32694,
|
|
City = "Dörentrup",
|
|
SapAccountNumber = 00000004,
|
|
EMail = "info@vdh-online.com",
|
|
PhoneNumber = "05265 945520",
|
|
DataStatus = Status.Active.ToString(),
|
|
AccountType = new() { AccountTypeCode = "SUP" },
|
|
SubMarket = new() { SubMarketCode = "SUP" }
|
|
};
|
|
seedAccounts.Add(vanderheijden);
|
|
|
|
Account ole = new() {
|
|
AccountName = "OLE DICH Instrumentmakers ApS",
|
|
AccountId = 5,
|
|
Street = "18, Taarnfalkevej",
|
|
Zip = 2650,
|
|
City = "Hvidovre, DENMARK",
|
|
SapAccountNumber = 00000005,
|
|
EMail = "",
|
|
PhoneNumber = "+45 36 78 41 85",
|
|
DataStatus = Status.Active.ToString(),
|
|
AccountType = new() { AccountTypeCode = "SUP" },
|
|
SubMarket = new() { SubMarketCode = "SUP" }
|
|
};
|
|
seedAccounts.Add(ole);
|
|
|
|
Account sprep = new() {
|
|
AccountName = "S-prep GmbH",
|
|
AccountId = 6,
|
|
Street = "Im Amann 7",
|
|
Zip = 88662,
|
|
City = "Überlingen",
|
|
SapAccountNumber = 00000006,
|
|
EMail = "info@s-prep.com",
|
|
PhoneNumber = "07551 932696",
|
|
FaxNumber = "07551-932699",
|
|
DataStatus = Status.Active.ToString(),
|
|
AccountType = new() { AccountTypeCode = "SUP" },
|
|
SubMarket = new() { SubMarketCode = "SUP" }
|
|
};
|
|
seedAccounts.Add(sprep);
|
|
|
|
Account hellma = new() {
|
|
AccountName = "Hellma GmbH & Co. KG",
|
|
AccountId = 7,
|
|
Street = "Klosterrunsstraße 5",
|
|
Zip = 79379,
|
|
City = "Müllheim",
|
|
SapAccountNumber = 00000007,
|
|
EMail = "info.de@hellma.com",
|
|
PhoneNumber = "07631 1820",
|
|
DataStatus = Status.Active.ToString(),
|
|
AccountType = new() { AccountTypeCode = "SUP" },
|
|
SubMarket = new() { SubMarketCode = "SUP" }
|
|
};
|
|
seedAccounts.Add(hellma);
|
|
|
|
Account glasside = new() {
|
|
AccountName = "Glasside Technologies",
|
|
AccountId = 8,
|
|
Street = "Albany House, 82 Avenue Road//PE19 1LH St Neots, Cambridgeshire//United Kingdom",
|
|
Zip = 0,
|
|
City = "St Neots, Cambridgesgire, UNITED KINGDOM",
|
|
SapAccountNumber = 00000008,
|
|
EMail = "",
|
|
PhoneNumber = "-/-",
|
|
DataStatus = Status.Active.ToString(),
|
|
AccountType = new() { AccountTypeCode = "SUP" },
|
|
SubMarket = new() { SubMarketCode = "SUP" }
|
|
};
|
|
seedAccounts.Add(glasside);
|
|
|
|
Account pike = new() {
|
|
AccountName = "PIKE Technologies Inc.",
|
|
AccountId = 9,
|
|
Street = "6125 Cottonwood Drive//Madison, WI 53719//USA",
|
|
Zip = 53719,
|
|
City = "Madison (WI), USA",
|
|
SapAccountNumber = 00000009,
|
|
EMail = "info@piketech.com",
|
|
PhoneNumber = "+1 608 274 2721",
|
|
FaxNumber = "+1 608 274 0103",
|
|
DataStatus = Status.Active.ToString(),
|
|
AccountType = new() { AccountTypeCode = "SUP" },
|
|
SubMarket = new() { SubMarketCode = "SUP" }
|
|
};
|
|
seedAccounts.Add(pike);
|
|
|
|
using (GremlinDb gremlinDb = new()) {
|
|
foreach (Account account in seedAccounts) {
|
|
// AccountType und SubMarket aus DB laden, damit der Datensatz vom Context verfolgt wird und EF Core nicht versucht, diesen standardmäßig neu anzulegen.
|
|
|
|
|
|
account.AccountType = ResolveAccountType(gremlinDb, account.AccountType.AccountTypeCode);
|
|
|
|
|
|
account.SubMarket = ResolveSubmarket(gremlinDb, account.SubMarket.SubMarketCode);
|
|
|
|
|
|
_ = MetaDataSetter.ForImport(account, "DbInitializer", "Function DbHelper.DbInitializer");
|
|
}
|
|
|
|
|
|
gremlinDb.Accounts.AddRange(seedAccounts);
|
|
|
|
_ = gremlinDb.SaveChanges();
|
|
}
|
|
|
|
//RegisteredUser
|
|
List<RegisteredUser> seedRegisteredUser = new();
|
|
|
|
RegisteredUser userSascha = new() { UserName = "woitsche", PasswordHash = "527646" };
|
|
seedRegisteredUser.Add(userSascha);
|
|
|
|
RegisteredUser userSebastian = new() { UserName = "sewelsch", PasswordHash = "123456" };
|
|
seedRegisteredUser.Add(userSebastian);
|
|
|
|
using (GremlinDb gremlinDb = new()) {
|
|
foreach (RegisteredUser userSetting in seedRegisteredUser) {
|
|
userSetting.DataCreationDate = DateTime.Now;
|
|
userSetting.DataModificationByUser = "DB Initializer";
|
|
userSetting.DataModificationDate = DateTime.Now;
|
|
}
|
|
|
|
|
|
gremlinDb.RegisteredUser.AddRange(seedRegisteredUser);
|
|
|
|
_ = gremlinDb.SaveChanges();
|
|
}
|
|
|
|
//RUSetting
|
|
List<RuSettings> seedRuSettings = new();
|
|
|
|
using (RuSettings saschaName = new()) {
|
|
saschaName.RegisteredUserId = 1;
|
|
saschaName.SettingKey = "userName";
|
|
saschaName.SettingValue = "Dr. Sascha Woitschetzki";
|
|
seedRuSettings.Add(saschaName);
|
|
}
|
|
|
|
using (RuSettings saschaPhone = new()) {
|
|
saschaPhone.RegisteredUserId = 1;
|
|
saschaPhone.SettingKey = "userPhone";
|
|
saschaPhone.SettingValue = "+49 208 74129134";
|
|
seedRuSettings.Add(saschaPhone);
|
|
}
|
|
|
|
using (RuSettings saschaMobile = new()) {
|
|
saschaMobile.RegisteredUserId = 1;
|
|
saschaMobile.SettingKey = "userMobile";
|
|
saschaMobile.SettingValue = "+49 176 22285334";
|
|
seedRuSettings.Add(saschaMobile);
|
|
}
|
|
|
|
using (RuSettings saschaMail = new()) {
|
|
saschaMail.RegisteredUserId = 1;
|
|
saschaMail.SettingKey = "userMail";
|
|
saschaMail.SettingValue = "sascha.woitschetzki@non.agilent.com";
|
|
seedRuSettings.Add(saschaMail);
|
|
}
|
|
|
|
using (RuSettings saschaTerritoryId = new()) {
|
|
saschaTerritoryId.RegisteredUserId = 1;
|
|
saschaTerritoryId.SettingKey = "userTerritoryID";
|
|
saschaTerritoryId.SettingValue = "83PE89";
|
|
seedRuSettings.Add(saschaTerritoryId);
|
|
}
|
|
|
|
using (RuSettings saschaTexRand = new()) {
|
|
saschaTexRand.RegisteredUserId = 1;
|
|
saschaTexRand.SettingKey = "texRand";
|
|
saschaTexRand.SettingValue = "2";
|
|
seedRuSettings.Add(saschaTexRand);
|
|
}
|
|
|
|
using (GremlinDb gremlinDb = new()) {
|
|
foreach (RuSettings userSetting in seedRuSettings) {
|
|
userSetting.DataCreationDate = DateTime.Now;
|
|
userSetting.DataModificationByUser = "DB Initializer";
|
|
userSetting.DataModificationDate = DateTime.Now;
|
|
}
|
|
|
|
|
|
gremlinDb.RuSettings.AddRange(seedRuSettings);
|
|
|
|
_ = gremlinDb.SaveChanges();
|
|
}
|
|
}
|
|
|
|
public static void InsertTestDataIntoDb() {
|
|
using (GremlinDb gremlinDb = new()) {
|
|
Random r = new();
|
|
|
|
Contact newContact = new() {
|
|
AcademicTitle = RandomString(9),
|
|
FirstName = RandomString(5),
|
|
LastName = RandomString(20),
|
|
Gender = (byte)Gender.Male,
|
|
Department = RandomString(9)
|
|
};
|
|
_ = MetaDataSetter.ForImport(newContact, "Tester", "Seeding data for testing.");
|
|
|
|
Account newAccount = new() {
|
|
AccountName = RandomString(20),
|
|
Street = RandomString(9),
|
|
Zip = Convert.ToUInt32(r.Next(11111, 99999)),
|
|
City = RandomString(9),
|
|
SapAccountNumber = Convert.ToUInt32(r.Next(1111111, 99999999)),
|
|
EMail = RandomString(9) + "@" + RandomString(9) + "." + RandomString(3),
|
|
PhoneNumber = "+49 " + r.Next()
|
|
};
|
|
_ = MetaDataSetter.ForImport(newAccount, "Tester", "Seeding data for testing.");
|
|
|
|
AccountType? accountType = gremlinDb.AccountTypes.FirstOrDefault(a => a.AccountTypeCode == "FPC")!;
|
|
|
|
newAccount.AccountType = accountType;
|
|
|
|
SubMarket subMarket = gremlinDb.SubMarkets.First(a => a.SubMarketCode == "CEN");
|
|
|
|
newAccount.SubMarket = subMarket;
|
|
newContact.Account = newAccount;
|
|
|
|
try {
|
|
_ = gremlinDb.Add(newAccount);
|
|
_ = gremlinDb.SaveChanges();
|
|
_ = gremlinDb.Add(newContact);
|
|
_ = gremlinDb.SaveChanges();
|
|
Console.WriteLine($"Account {newAccount.AccountName} mit Contact {newContact.LastName} wurde angelegt.");
|
|
}
|
|
catch (Exception e) {
|
|
Console.WriteLine(e.Message);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static bool ImportContactsFromCsv(string filepath = "", string separator = ";", bool dataHasHeading = true) {
|
|
//Wenn keine Datei ausgewählt (Cancel geklickt), dann Abbruch:
|
|
if (filepath == "") return false;
|
|
|
|
List<Contact> contactsReadFromFile = new(8000);
|
|
// ENCODING CHANGED TO UNICODE. TO BE TESTED!
|
|
using (TextFieldParser csvParser = new(filepath, FileService.GetEncoding(filepath))) {
|
|
//Parser configuration:
|
|
csvParser.Delimiters = new[] { separator };
|
|
csvParser.CommentTokens = new[] { "#" };
|
|
csvParser.HasFieldsEnclosedInQuotes = true;
|
|
|
|
// Skip the row with the column names:
|
|
if (dataHasHeading) _ = csvParser.ReadLine();
|
|
|
|
while (!csvParser.EndOfData) {
|
|
// Read current line fields, pointer moves to the next line.
|
|
Contact importedContact = new();
|
|
string[] fields = csvParser.ReadFields()!;
|
|
|
|
//No conversion
|
|
importedContact.AcademicTitle = fields[1];
|
|
importedContact.FirstName = fields[3];
|
|
importedContact.LastName = fields[4];
|
|
importedContact.EMail = fields[6];
|
|
importedContact.Department = fields[7];
|
|
importedContact.Room = fields[8];
|
|
importedContact.PhoneNumber = fields[9];
|
|
importedContact.Function = fields[10];
|
|
importedContact.MobileNumber = fields[13];
|
|
|
|
//Convert Gender
|
|
importedContact.Gender = fields[2] == "M" ? (byte)Gender.Male : fields[2] == "F" ? (byte)Gender.Female : (byte)Gender.Unknown;
|
|
|
|
//Convert OptIn Status
|
|
importedContact.OptInStatus = fields[5] switch {
|
|
"Opt In" => true,
|
|
"Opt Out" => false,
|
|
_ => false
|
|
};
|
|
|
|
//Convert "SAP Contact Number"
|
|
try {
|
|
importedContact.SapContactNumber = Convert.ToUInt32(fields[11], CultureInfo.CurrentCulture);
|
|
}
|
|
catch (FormatException ex) {
|
|
//errorhandling here: "Unable to parse input: " + field[0] + " as uint"
|
|
//Zeilennummer, Feld und Wert in Liste speichern, um am Ende gesammelt auszugeben
|
|
string errorRaiser = fields[11];
|
|
if (errorRaiser == "") errorRaiser = "No Contact Number in this row!";
|
|
|
|
DisplayErrorDetails(ex, errorRaiser);
|
|
return false;
|
|
}
|
|
catch (OverflowException ex) {
|
|
//errorhandling here: "Number cannot fit in an Uint."
|
|
//Zeilennummer, Feld und Wert in Liste speichern, um am Ende gesammelt auszugeben
|
|
string errorRaiser = fields[11];
|
|
if (errorRaiser == "") errorRaiser = "No Contact Number in this row!";
|
|
|
|
DisplayErrorDetails(ex, errorRaiser);
|
|
return false;
|
|
}
|
|
|
|
//Convert "Account Created on"
|
|
int year = Convert.ToInt32(fields[12].Substring(0, 4), CultureInfo.CurrentCulture);
|
|
int month = Convert.ToInt32(fields[12].Substring(4, 2), CultureInfo.CurrentCulture);
|
|
int day = Convert.ToInt32(fields[12].Substring(6, 2), CultureInfo.CurrentCulture);
|
|
importedContact.SapContactCreationDate = new(year, month, day);
|
|
|
|
//Convert "No Phone Calls"
|
|
if (fields[26] == "1") importedContact.NoPhoneCalls = true;
|
|
|
|
//Convert "No Hardcopy Mailing"
|
|
if (fields[27] == "1") importedContact.NoHardcopyMailing = true;
|
|
|
|
//SAPAccountID in Contact.Notes speichern, um den entsprechenden Account aus DB heraussuchen zu können:
|
|
importedContact.Notes = fields[0];
|
|
|
|
contactsReadFromFile.Add(importedContact);
|
|
}
|
|
|
|
//Eingelesenen Account in DB schreiben:
|
|
using (GremlinDb gremlinDb = new()) {
|
|
foreach (Contact contact in contactsReadFromFile) {
|
|
// AccountID aus DB laden, damit der Datensatz vom Context verfolgt wird und EF Core nicht versucht, diesen standardmäßig neu anzulegen.
|
|
|
|
contact.Account = ResolveAccountById(gremlinDb, uint.Parse(contact.Notes));
|
|
|
|
contact.Notes = "";
|
|
_ = MetaDataSetter.ForImport(contact, "CSVImporter", "Initial import by CSV Importer (Function DbHelper.ImportContactsFromCSV)");
|
|
}
|
|
|
|
|
|
gremlinDb.Contacts.AddRange(contactsReadFromFile);
|
|
|
|
_ = gremlinDb.SaveChanges();
|
|
}
|
|
}
|
|
|
|
//Bestätigung senden
|
|
Console.WriteLine($"Es wurden {contactsReadFromFile.Count} Contacts erfolgreich der Datenbank hinzugefügt.");
|
|
return true;
|
|
}
|
|
|
|
private static bool ImportAccountsFromCsv(string filepath = "", string separator = ";", bool dataHasHeading = true) {
|
|
//Wenn keine Datei ausgewählt (Cancel geklickt), dann Abbruch:
|
|
if (filepath == "") return false;
|
|
|
|
List<Account> accountsReadFromFile = new(2000);
|
|
|
|
//ENCODING CHANGED TO ISO-8859-1 AS EQUIVALENT (?) TO "LATIN1" (unavailable). TO BE TESTED!
|
|
//ich würde mir ja UTF8 als universelles Encoding wünschen
|
|
|
|
using (TextFieldParser csvParser = new(filepath, FileService.GetEncoding(filepath))) {
|
|
//Parser configuration:
|
|
csvParser.Delimiters = new[] { separator };
|
|
csvParser.CommentTokens = new[] { "#" };
|
|
csvParser.HasFieldsEnclosedInQuotes = true;
|
|
|
|
// Skip the row with the column names:
|
|
if (dataHasHeading) _ = csvParser.ReadLine();
|
|
|
|
while (!csvParser.EndOfData) {
|
|
// Read current line fields, pointer moves to the next line.
|
|
Account importedAccount = new();
|
|
{
|
|
importedAccount.SubMarket = new();
|
|
importedAccount.AccountType = new();
|
|
importedAccount.Contacts = new List<Contact>();
|
|
}
|
|
string[] fields = csvParser.ReadFields()!;
|
|
|
|
//Konvertierung erforderlich:
|
|
try {
|
|
importedAccount.SapAccountNumber = Convert.ToUInt32(fields[0]);
|
|
}
|
|
catch (FormatException ex) {
|
|
//errorhandling here: "Unable to parse input: " + field[0] + " as uint"
|
|
//Zeilennummer, Feld und Wert in Liste speichern, um am Ende gesammelt auszugeben
|
|
string errorRaiser = fields[0];
|
|
if (errorRaiser == "") errorRaiser = "No Account Number in this row!";
|
|
|
|
DisplayErrorDetails(ex, errorRaiser);
|
|
return false;
|
|
}
|
|
catch (OverflowException ex) {
|
|
//errorhandling here: "Number cannot fit in an Uint."
|
|
//Zeilennummer, Feld und Wert in Liste speichern, um am Ende gesammelt auszugeben
|
|
string errorRaiser = fields[0];
|
|
if (errorRaiser == "") errorRaiser = "No Account Number in this row!";
|
|
|
|
DisplayErrorDetails(ex, errorRaiser);
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
importedAccount.Zip = Convert.ToUInt32(fields[2]);
|
|
}
|
|
catch (FormatException ex) {
|
|
//errorhandling here: "Unable to parse input: " + field[0] + " as uint"
|
|
//Zeilennummer, Feld und Wert in Liste speichern, um am Ende gesammelt auszugeben
|
|
string errorRaiser = fields[0];
|
|
if (errorRaiser == "") errorRaiser = "No ZIP in this row!";
|
|
|
|
DisplayErrorDetails(ex, errorRaiser);
|
|
return false;
|
|
}
|
|
catch (OverflowException ex) {
|
|
//errorhandling here: "Number cannot fit in an Uint."
|
|
//Zeilennummer, Feld und Wert in Liste speichern, um am Ende gesammelt auszugeben
|
|
string errorRaiser = fields[0];
|
|
if (errorRaiser == "") errorRaiser = "No ZIP in this row!";
|
|
|
|
DisplayErrorDetails(ex, errorRaiser);
|
|
return false;
|
|
}
|
|
|
|
//Konvertierung für AccountCreatedinSAPOn Property:
|
|
//Test auf Inhalt
|
|
if (fields[8].Length != 0) {
|
|
int year = Convert.ToInt32(fields[8].Substring(0, 4));
|
|
int month = Convert.ToInt32(fields[8].Substring(4, 2));
|
|
int day = Convert.ToInt32(fields[8].Substring(6, 2));
|
|
importedAccount.AccountCreatedInSapOn = new(year, month, day);
|
|
}
|
|
|
|
//keine Konvertierung nötig:
|
|
importedAccount.AccountName = fields[1];
|
|
importedAccount.City = fields[3];
|
|
importedAccount.Street = fields[4];
|
|
importedAccount.SubMarket.SubMarketCode = fields[5];
|
|
importedAccount.SubMarket.DataStatus = Status.Active.ToString();
|
|
importedAccount.AccountType.AccountTypeCode = fields[6];
|
|
importedAccount.AccountType.DataStatus = Status.Active.ToString();
|
|
importedAccount.PhoneNumber = fields[7];
|
|
importedAccount.DataStatus = Status.Active.ToString();
|
|
|
|
accountsReadFromFile.Add(importedAccount);
|
|
}
|
|
}
|
|
|
|
//Eingelesenen Account in DB schreiben:
|
|
using (GremlinDb gremlinDb = new()) {
|
|
foreach (Account account in accountsReadFromFile) {
|
|
// AccountType aus DB laden, damit der Datensatz vom Context verfolgt wird und EF Core nicht versucht, diesen standardmäßig neu anzulegen.
|
|
|
|
if (account.AccountType.AccountTypeCode != "") {
|
|
AccountType? accountType = gremlinDb.AccountTypes.First(a => a.AccountTypeCode == account.AccountType.AccountTypeCode);
|
|
|
|
account.AccountType = accountType;
|
|
|
|
account.AccountType = ResolveAccountType(gremlinDb, account.AccountType.AccountTypeCode);
|
|
}
|
|
|
|
else {
|
|
//Default
|
|
account.AccountType = ResolveAccountType(gremlinDb, "FPC");
|
|
}
|
|
|
|
|
|
if (account.SubMarket.SubMarketCode != "") {
|
|
SubMarket subMarket = gremlinDb.SubMarkets.First(a => a.SubMarketCode == account.SubMarket.SubMarketCode);
|
|
|
|
account.SubMarket = subMarket;
|
|
|
|
|
|
account.AccountType = ResolveAccountType(gremlinDb, account.AccountType.AccountTypeCode);
|
|
|
|
|
|
account.SubMarket = ResolveSubmarket(gremlinDb, account.SubMarket.SubMarketCode);
|
|
}
|
|
else {
|
|
//Default
|
|
account.SubMarket = ResolveSubmarket(gremlinDb, "COT");
|
|
}
|
|
|
|
_ = MetaDataSetter.ForImport(account, "CSVImporter", "Initial import by CSV Importer (Function DbHelper.ImportAccountsFromCSV)");
|
|
}
|
|
|
|
|
|
gremlinDb.Accounts.AddRange(accountsReadFromFile);
|
|
|
|
_ = gremlinDb.SaveChanges();
|
|
}
|
|
|
|
//Bestätigung senden
|
|
Console.WriteLine($"Es wurden {accountsReadFromFile.Count} Accounts erfolgreich der Datenbank hinzugefügt.");
|
|
|
|
return true;
|
|
}
|
|
|
|
private static bool ImportLsagContactListToolData(string filepath = "", string separator = ";") {
|
|
if (filepath == "") return false; //Wenn keine Datei ausgewählt (Cancel geklickt), dann Abbruch:
|
|
|
|
List<Contact> contactsReadFromFile = new(8000);
|
|
List<Account> accountsReadFromFile = new(2000);
|
|
|
|
using (TextFieldParser csvParser = new(filepath, FileService.GetEncoding(filepath))) {
|
|
//Parser configuration:
|
|
csvParser.Delimiters = new[] { separator };
|
|
csvParser.CommentTokens = new[] { "#" };
|
|
csvParser.HasFieldsEnclosedInQuotes = true;
|
|
|
|
//dynamische Spaltenzuordnung in Dictonary speichern
|
|
string[] fields = csvParser.ReadFields()!;
|
|
Dictionary<string, int> columnNumberOf = ColumnMapping(fields);
|
|
|
|
//Daten einlesen und Accounts und Kontakte in eigene List<Account> bzw List<Contact> extrahieren.
|
|
while (!csvParser.EndOfData) {
|
|
bool dataHasError = false;
|
|
Account importedAccount = new();
|
|
Contact importedContact = new();
|
|
importedAccount.SubMarket = new();
|
|
importedAccount.AccountType = new();
|
|
importedContact.Account = new();
|
|
|
|
fields = csvParser.ReadFields()!; // Read current line fields, pointer moves to the next line.
|
|
if (fields[0] == "") break; // Am Ende hängt eine leere Zeile, die im Parser einen Fehler auslösen würde.
|
|
|
|
//Account-Daten
|
|
// Konvertierung erforderlich:
|
|
try {
|
|
importedAccount.SapAccountNumber = Convert.ToUInt32(fields[columnNumberOf["SAPAccountNumber"]]);
|
|
}
|
|
catch (FormatException ex) {
|
|
//errorhandling here: "Unable to parse input: " + field[0] + " as uint"
|
|
//Zeilennummer, Feld und Wert in Liste speichern, um am Ende gesammelt auszugeben
|
|
string errorRaiser = fields[columnNumberOf["SAPContactNumber"]];
|
|
if (errorRaiser == "") errorRaiser = "No Contact Number in this row!";
|
|
|
|
DisplayErrorDetails(ex, errorRaiser);
|
|
return false;
|
|
}
|
|
catch (OverflowException ex) {
|
|
//errorhandling here: "Number cannot fit in an Uint."
|
|
//Zeilennummer, Feld und Wert in Liste speichern, um am Ende gesammelt auszugeben
|
|
string errorRaiser = fields[columnNumberOf["SAPContactNumber"]];
|
|
if (errorRaiser == "") errorRaiser = "No Contact Number in this row!";
|
|
|
|
DisplayErrorDetails(ex, errorRaiser);
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
importedAccount.Zip = Convert.ToUInt32(fields[columnNumberOf["ZIP"]]);
|
|
}
|
|
catch (FormatException ex) {
|
|
//errorhandling here: "Unable to parse input: " + field[0] + " as uint"
|
|
//Zeilennummer, Feld und Wert in Liste speichern, um am Ende gesammelt auszugeben
|
|
string errorRaiser = fields[columnNumberOf["SAPContactNumber"]];
|
|
if (errorRaiser == "") errorRaiser = "No Contact Number in this row!";
|
|
|
|
DisplayErrorDetails(ex, errorRaiser);
|
|
return false;
|
|
}
|
|
catch (OverflowException ex) {
|
|
//errorhandling here: "Number cannot fit in an Uint."
|
|
//Zeilennummer, Feld und Wert in Liste speichern, um am Ende gesammelt auszugeben
|
|
string errorRaiser = fields[columnNumberOf["SAPContactNumber"]];
|
|
if (errorRaiser == "") errorRaiser = "No Contact Number in this row!";
|
|
|
|
DisplayErrorDetails(ex, errorRaiser);
|
|
return false;
|
|
}
|
|
|
|
// Konvertierung für AccountCreatedinSAPOn Property:
|
|
int year = Convert.ToInt32(fields[columnNumberOf["AccountCreatedInSAPOn"]].Substring(0, 4));
|
|
int month = Convert.ToInt32(fields[columnNumberOf["AccountCreatedInSAPOn"]].Substring(4, 2));
|
|
int day = Convert.ToInt32(fields[columnNumberOf["AccountCreatedInSAPOn"]].Substring(6, 2));
|
|
importedAccount.AccountCreatedInSapOn = new(year, month, day);
|
|
|
|
//Convert City von Großschreibung zu Normalschreibung
|
|
importedAccount.City = fields[columnNumberOf["City"]].First() + fields[columnNumberOf["City"]].Substring(1).ToLower();
|
|
|
|
// keine Konvertierung nötig:
|
|
importedAccount.AccountName = fields[columnNumberOf["AccountName"]];
|
|
importedAccount.Street = fields[columnNumberOf["Street"]];
|
|
importedAccount.SubMarket.SubMarketCode = fields[columnNumberOf["SubMarketCode"]];
|
|
importedAccount.SubMarket.DataStatus = Status.Active.ToString();
|
|
importedAccount.AccountType.AccountTypeCode = fields[columnNumberOf["AccountTypeCode"]];
|
|
importedAccount.AccountType.DataStatus = Status.Active.ToString();
|
|
importedAccount.PhoneNumber = fields[columnNumberOf["AccountPhoneNumber"]];
|
|
importedAccount.DataStatus = Status.Active.ToString();
|
|
|
|
//Validierungen:
|
|
if (importedAccount.AccountName == "" || importedAccount.City == "" || importedAccount.Street == "" || importedAccount.SubMarket.SubMarketCode == "" || importedAccount.AccountType.AccountTypeCode == "" || importedAccount.SapAccountNumber == 0) dataHasError = true;
|
|
|
|
//Validierten Account der Liste hinzufügen:
|
|
if (dataHasError == false) _ = importedAccount.AddIfUniqueTo(accountsReadFromFile);
|
|
|
|
//Contact-Daten
|
|
// Ohne Konvertierung
|
|
importedContact.AcademicTitle = fields[columnNumberOf["AcademicTitle"]];
|
|
importedContact.FirstName = fields[columnNumberOf["FirstName"]];
|
|
importedContact.LastName = fields[columnNumberOf["LastName"]];
|
|
importedContact.EMail = fields[columnNumberOf["EMail"]];
|
|
importedContact.Department = fields[columnNumberOf["Department"]];
|
|
importedContact.Room = fields[columnNumberOf["Room"]];
|
|
importedContact.PhoneNumber = fields[columnNumberOf["PhoneNumber"]];
|
|
importedContact.Function = fields[columnNumberOf["Function"]];
|
|
importedContact.MobileNumber = fields[columnNumberOf["MobileNumber"]];
|
|
|
|
//Convert Gender
|
|
importedContact.Gender = fields[columnNumberOf["Gender"]] == "M" ? (byte)Gender.Male : fields[columnNumberOf["Gender"]] == "F" ? (byte)Gender.Female : (byte)Gender.Unknown;
|
|
|
|
//Convert OptIn Status
|
|
importedContact.OptInStatus = fields[columnNumberOf["OptInStatus"]] == "Opt In" || (fields[columnNumberOf["OptInStatus"]] == "Opt Out" && false);
|
|
|
|
//Convert "SAP Contact Number"
|
|
try {
|
|
importedContact.SapContactNumber = Convert.ToUInt32(fields[columnNumberOf["SAPContactNumber"]]);
|
|
}
|
|
catch (FormatException ex) {
|
|
//errorhandling here: "Unable to parse input: " + field[0] + " as uint"
|
|
//Zeilennummer, Feld und Wert in Liste speichern, um am Ende gesammelt auszugeben
|
|
string errorRaiser = fields[columnNumberOf["SAPContactNumber"]];
|
|
if (errorRaiser == "") errorRaiser = "No Contact Number in this row!";
|
|
|
|
DisplayErrorDetails(ex, errorRaiser);
|
|
return false;
|
|
}
|
|
catch (OverflowException ex) {
|
|
//errorhandling here: "Number cannot fit in an Uint."
|
|
//Zeilennummer, Feld und Wert in Liste speichern, um am Ende gesammelt auszugeben
|
|
string errorRaiser = fields[columnNumberOf["SAPContactNumber"]];
|
|
if (errorRaiser == "") errorRaiser = "No Contact Number in this row!";
|
|
|
|
DisplayErrorDetails(ex, errorRaiser);
|
|
return false;
|
|
}
|
|
|
|
//Convert "Account Created on"
|
|
year = Convert.ToInt32(fields[columnNumberOf["AccountCreatedInSAPOn"]].Substring(0, 4));
|
|
month = Convert.ToInt32(fields[columnNumberOf["AccountCreatedInSAPOn"]].Substring(4, 2));
|
|
day = Convert.ToInt32(fields[columnNumberOf["AccountCreatedInSAPOn"]].Substring(6, 2));
|
|
importedContact.SapContactCreationDate = new(year, month, day);
|
|
|
|
//Convert "No Phone Calls"
|
|
if (fields[columnNumberOf["NoPhoneCalls"]] == "1") importedContact.NoPhoneCalls = true;
|
|
|
|
//Convert "No Hardcopy Mailing"
|
|
if (fields[columnNumberOf["NoHardcopyMailing"]] == "1") importedContact.NoHardcopyMailing = true;
|
|
|
|
//SAPAccountID in Contact.Notes speichern, um den entsprechenden Account aus DB heraussuchen zu können:
|
|
importedContact.Notes = fields[columnNumberOf["SAPAccountNumber"]];
|
|
|
|
//Validierungen:
|
|
if (importedContact.EmailBounced || importedContact.LastName == "" || importedContact.SapContactNumber == 0) dataHasError = true;
|
|
|
|
if (importedContact.EMail.Length > 7 && importedContact.EMail.Substring(0, 8) == "bounced-") dataHasError = true;
|
|
|
|
//Validierte Kontakte zu Liste hinzufügen:
|
|
if (dataHasError == false) contactsReadFromFile.Add(importedContact);
|
|
}
|
|
}
|
|
|
|
//Eingelesenen Account in DB schreiben:
|
|
using (GremlinDb gremlinDb = new()) {
|
|
foreach (Account account in accountsReadFromFile) {
|
|
// AccountType aus DB laden, damit der Datensatz vom Context verfolgt wird und EF Core nicht versucht, diesen standardmäßig neu anzulegen.
|
|
|
|
|
|
AccountType? accountType = gremlinDb.AccountTypes.First(a => a.AccountTypeCode == account.AccountType.AccountTypeCode);
|
|
|
|
|
|
account.AccountType = accountType;
|
|
|
|
|
|
SubMarket subMarket = gremlinDb.SubMarkets.First(a => a.SubMarketCode == account.SubMarket.SubMarketCode);
|
|
|
|
|
|
account.SubMarket = subMarket;
|
|
|
|
account.AccountType = ResolveAccountType(gremlinDb, account.AccountType.AccountTypeCode);
|
|
|
|
account.SubMarket = ResolveSubmarket(gremlinDb, account.SubMarket.SubMarketCode);
|
|
|
|
_ = MetaDataSetter.ForImport(account, "CSVImporter", "Initial import by CSV Importer (Function DbHelper.ImportAccountsFromCSV)");
|
|
}
|
|
|
|
|
|
gremlinDb.Accounts.AddRange(accountsReadFromFile);
|
|
|
|
_ = gremlinDb.SaveChanges();
|
|
}
|
|
|
|
//Eingelesenen Contacts in DB schreiben:
|
|
using (GremlinDb db = new()) {
|
|
foreach (Contact contact in contactsReadFromFile) {
|
|
contact.Account = ResolveAccountById(db, uint.Parse(contact.Notes));
|
|
|
|
contact.Notes = "";
|
|
_ = MetaDataSetter.ForImport(contact, "CSVImporter", "Initial import by CSV Importer (Function DbHelper.ImportContactsFromCSV)");
|
|
}
|
|
|
|
|
|
db.Contacts.AddRange(contactsReadFromFile);
|
|
|
|
_ = db.SaveChanges();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private static bool ImportProductsFromCsv(string filepath = "", string separator = "|", bool dataHasHeading = true) {
|
|
if (filepath == "") return false; //Wenn keine Datei ausgewählt (Cancel geklickt), dann Abbruch.
|
|
|
|
List<Product> productsReadFromFile = new(ParseProductFile(filepath, separator, dataHasHeading));
|
|
return InsertProducts(productsReadFromFile);
|
|
}
|
|
|
|
private static bool ImportCustomDescriptionsFromCsv(string filepath = "", string separator = "|", bool dataHasHeading = true) {
|
|
if (filepath == "") return false; //Wenn keine Datei ausgewählt (Cancel geklickt), dann Abbruch:
|
|
|
|
List<CustomDescription> cDsReadFromFile = new(2500);
|
|
using (TextFieldParser csvParser = new(filepath, Encoding.GetEncoding("UTF-8"))) {
|
|
//Parser configuration:
|
|
csvParser.Delimiters = new[] { separator };
|
|
csvParser.CommentTokens = new[] { "#" };
|
|
csvParser.HasFieldsEnclosedInQuotes = true;
|
|
|
|
// Skip the row with the column names:
|
|
if (dataHasHeading) _ = csvParser.ReadLine();
|
|
|
|
while (!csvParser.EndOfData) {
|
|
// Read current line fields, pointer moves to the next line.
|
|
string[] fields = csvParser.ReadFields()!;
|
|
|
|
//string productNumber = fields[0];
|
|
//string? optionNumber = fields[1] == "" ? null : fields[1];
|
|
CustomDescription importedCd = new() {
|
|
ProductNumber = fields[0],
|
|
OptionNumber = fields[1],
|
|
Heading = fields[3],
|
|
DescriptionText = fields[4],
|
|
CoverletterText = fields[5],
|
|
Notes = fields[6]
|
|
// Product = new Product()
|
|
// Supplier = new()
|
|
// {
|
|
// AccountName = fields[2] is "" or "RB" ? "Agilent Technologies" : fields[2]
|
|
// }
|
|
};
|
|
|
|
_ = MetaDataSetter.ForImport(importedCd, "Importer", "Initial Importer by CD-ImporterFomCsv");
|
|
cDsReadFromFile.Add(importedCd);
|
|
}
|
|
}
|
|
|
|
//Eingelesenen Custum Desciptions in DB schreiben:
|
|
//Check for 3PPs that not yet in the db.
|
|
//Step 1a: Add 3PP-Products from CD-List to list
|
|
//Step 1b: Add list to db.
|
|
//Step 2: Add CDs to products.
|
|
|
|
using (GremlinDb gremlinDb = new()) {
|
|
//Step 1a
|
|
List<Product> thirdPartyProductsFromImportedCDs = new();
|
|
foreach (CustomDescription cd in cDsReadFromFile)
|
|
if (cd.Supplier.AccountName != "Agilent Technologies") {
|
|
Product new3PpProduct = new() {
|
|
// CustomDescription = cd,
|
|
HasBreakPrices = false,
|
|
ListPrice = 0,
|
|
ProductNumber = cd.ProductNumber,
|
|
OptionNumber = cd.OptionNumber,
|
|
ProductStatus = Status.Active.ToString(),
|
|
SapLongDescription = "",
|
|
SapShortDescription = "",
|
|
Weight = 0,
|
|
IntroductionDate = DateTime.Now.Date,
|
|
BreakRangeFrom = 0,
|
|
BreakRangeTo = 0,
|
|
ProductLine = ResolveProductLine(gremlinDb, "3P")
|
|
};
|
|
|
|
// new3PpProduct.CustomDescription.Supplier = ResolveAccountByName(gremlinDb, new3PpProduct.CustomDescription.Supplier.AccountName);
|
|
_ = MetaDataSetter.ForImport(new3PpProduct, "Custom Desciption Importer", "Created at import from Custom Descriptions.");
|
|
|
|
thirdPartyProductsFromImportedCDs.Add(new3PpProduct);
|
|
}
|
|
|
|
|
|
//Step 1b
|
|
|
|
gremlinDb.Products.AddRange(thirdPartyProductsFromImportedCDs); //Imports both the products and the associated custom descriptions!
|
|
|
|
_ = gremlinDb.SaveChanges();
|
|
|
|
// Produkt aus DB laden, damit der Datensatz vom Context verfolgt wird und EF Core nicht versucht, diesen standardmäßig neu anzulegen.
|
|
//Step 2
|
|
List<CustomDescription> importedCDsWithEfReferences = new(100000);
|
|
List<CustomDescription> cDsWithoutEfReferences = new(1000); //nur zur Kontrolle, wird nicht verwendet.
|
|
List<Product> productsInDb = gremlinDb.Products.ToList();
|
|
|
|
Account agilent = gremlinDb.Accounts.Single(a => a.AccountName == "Agilent Technologies");
|
|
|
|
// foreach (CustomDescription cd in cDsReadFromFile.Where(cd => !thirdPartyProductsFromImportedCDs.Equals(cd.Product)))
|
|
// {
|
|
// //Establish EF Reference. If no PN/Opt found, then skip this custom description.
|
|
// //CD.Product = GetProduct(db, CD.ProductNumber, CD.OptionNumber); //ResolveXY-functions return null, if no match is found in db.
|
|
// // cd.Product = productsInDb.Where(product => product.ProductNumber == cd.ProductNumber && product.OptionNumber == cd.OptionNumber).FirstOrDefault();
|
|
//
|
|
// //Establish EF Reference: If no Supplier-Account found, then skip this custom description (shouldn't happen), else set Supplier to Agilent (3PP-Supplier have been processed before and their products should not be part of this list).
|
|
// cd.Supplier = agilent;
|
|
// _ = MetaDataSetter.ForImport(cd, "CSVImporter", "Initial import by CSV Importer (Function DbHelper.ImportCustomDescriptionsFromCsv)");
|
|
//
|
|
// //add to final list of CDs, that will go into the db.
|
|
// importedCDsWithEfReferences.Add(cd);
|
|
// }
|
|
|
|
|
|
gremlinDb.CustomDescriptions.AddRange(importedCDsWithEfReferences);
|
|
|
|
_ = gremlinDb.SaveChanges();
|
|
|
|
//Bestätigung senden
|
|
Console.WriteLine($"Es wurden {importedCDsWithEfReferences.Count} eigene Beschreibungen erfolgreich der Datenbank hinzugefügt.{Environment.NewLine}Es wurden {thirdPartyProductsFromImportedCDs.Count} 3PP-Produkte neu angelegt.");
|
|
return true;
|
|
}
|
|
}
|
|
|
|
//public static bool ImportCustomDescriptionsFromDocx(string filepath = "")
|
|
/////Importiert Eigene Beschreibungen aus Word-Dokument
|
|
/////Abkürzung: CD = CustomDescriptions
|
|
//{
|
|
// if (filepath == "")
|
|
// {
|
|
// //filepath = FileIO.GetFilepathFromUser("Word-Dokument|*.doc; *.docx; *.docm"); //Pfad abfragen über Dtei-Öffnen-Dialog:
|
|
// }
|
|
|
|
// if (filepath == "")
|
|
// {
|
|
// return false; //Wenn keine Datei ausgewählt (Cancel geklickt), dann Abbruch:
|
|
// }
|
|
|
|
// List<CustomDescription> importedCDs = new(2500);
|
|
// WordprocessingDocument CDDoc = WordprocessingDocument.Open(filepath, false); //alternativ in using-Block packen, dann kann man nicht das Document.Close vergessen.
|
|
// Table CDTable = CDDoc.MainDocumentPart.Document.Body.Elements<Table>().ElementAt(0); //alternativ: Elements<Table>.First()
|
|
// if (CDTable != null)
|
|
// {
|
|
// CDTable.Descendants<TableRow>().First().Remove(); //Überschriften löschen
|
|
// foreach (TableRow aRow in CDTable.Descendants<TableRow>()) //einmal durch den XML-Baum wandern: WordprocessingDocument -> MainDocumentPart -> Document -> Body -> Table -> TableRow -> TableCell -> Paragraph -> Run -> Text
|
|
// {
|
|
// CustomDescription importedCD = new();
|
|
// List<string> stringsRead = new();
|
|
|
|
// foreach (TableCell aCell in aRow.Descendants<TableCell>())
|
|
// {
|
|
// StringBuilder sb = new();
|
|
// StringBuilder note = new();
|
|
// foreach (Paragraph aParagraph in aCell.Descendants<Paragraph>())
|
|
// {
|
|
// foreach (Run aRun in aParagraph.Descendants<Run>())
|
|
// {
|
|
// foreach (Text aText in aRun.Descendants<Text>())
|
|
// {
|
|
// string temp = "";
|
|
// temp = aParagraph.Descendants<Run>()
|
|
// .Where(r => r.RunProperties.Vanish != null)
|
|
// .Aggregate("", (text, r) => text += r.InnerText); //nach hidden Text filtern, diesen in "note" speichern
|
|
// _ = note.Append(temp);
|
|
|
|
// if (temp == "") //true, falls kein hidden Text => normalen Text verketten...
|
|
// {
|
|
// _ = sb.Append(aText.InnerText);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// stringsRead.Add(sb.ToString()); //...und zellenweise abspeichern
|
|
// if (note.ToString() != "")
|
|
// {
|
|
// importedCD.Notes = note.ToString();
|
|
// }
|
|
// }
|
|
|
|
// importedCD.ProductNumber = stringsRead.ElementAt(0);
|
|
// importedCD.OptionNumber = stringsRead.ElementAt(1) == "" ? null : stringsRead.ElementAt(1);
|
|
// importedCD.Supplier.AccountName = stringsRead.ElementAt(2) is "" or "RB" ? "Agilent Technologies" : stringsRead.ElementAt(2);
|
|
// importedCD.Heading = stringsRead.ElementAt(3);
|
|
// importedCD.DescriptionText = stringsRead.ElementAt(4);
|
|
// importedCD.CoverletterText = stringsRead.ElementAt(5);
|
|
|
|
// importedCDs.Add(importedCD);
|
|
// //if (importedCDs.Count >= 1200 && importedCDs.Count % 100 == 0) MessageBox.Show(importedCDs.Count.ToString()); //DEBUGGING
|
|
|
|
// }
|
|
// }
|
|
// //MessageBox.Show(importedCDs.Count.ToString()); //DEBUGGING
|
|
// CDDoc.Close();
|
|
|
|
// //Eingelesenen Custum Desciptions in DB schreiben:
|
|
// //Check for 3PPs that not yet in the db.
|
|
// //Step 1a: Add 3PP-Products from CD-List to list
|
|
// //Step 1b: Add list to db.
|
|
// //Step 2: Add CDs to products.
|
|
|
|
// using (GremlinContext db = new())
|
|
// {
|
|
// //Step 1a
|
|
// List<Product> thirdPartyProductsFromImportedCDs = new();
|
|
// foreach (CustomDescription CD in importedCDs)
|
|
// {
|
|
// if (CD.Supplier.AccountName != "Agilent Technologies")
|
|
// {
|
|
// Product new3PPProduct = new()
|
|
// {
|
|
// CustomDescription = CD,
|
|
// HasBreakPrices = false,
|
|
// ListPrice = 0,
|
|
// ProductNumber = CD.ProductNumber,
|
|
// OptionNumber = CD.OptionNumber,
|
|
// ProductStatus = Status.Active.ToString(),
|
|
// SapLongDescription = null,
|
|
// SapShortDescription = null,
|
|
// Weight = 0,
|
|
// IntroductionDate = DateTime.Now.Date,
|
|
// BreakRangeFrom = 0,
|
|
// BreakRangeTo = 0,
|
|
// ProductLine = ResolveProductLine(db, "3P")
|
|
// };
|
|
// new3PPProduct.CustomDescription.Supplier = ResolveAccountByName(db, new3PPProduct.CustomDescription.Supplier.AccountName);
|
|
// _ = MetaDataSetter.ForImport(new3PPProduct, "Custom Desciption Importer", "Created at import from Custom Descriptions.");
|
|
|
|
// thirdPartyProductsFromImportedCDs.Add(new3PPProduct);
|
|
// }
|
|
// };
|
|
|
|
// //Step 1b
|
|
// db.Products.AddRange(thirdPartyProductsFromImportedCDs); //Imports both the products and the associated custom descriptions!
|
|
// _ = db.SaveChanges();
|
|
|
|
// // Produkt aus DB laden, damit der Datensatz vom Context verfolgt wird und EF Core nicht versucht, diesen standardmäßig neu anzulegen.
|
|
// //Step 2
|
|
// List<CustomDescription> importedCDsWithEFReferences = new();
|
|
// List<CustomDescription> CDsWithoutEFReferences = new(); //nur zur Kontrolle, wird nicht verwendet.
|
|
// foreach (CustomDescription CD in importedCDs)
|
|
// {
|
|
// //Skip Desciptions, if it has been already imported above (as part from 3PP)
|
|
// if (thirdPartyProductsFromImportedCDs.Intersect(CD.Products).Any())
|
|
// {
|
|
// continue;
|
|
// }
|
|
|
|
// //Establish EF Reference. If no PN/Opt found, then skip this custom description.
|
|
// CD.Products.Add(ResolveProduct(db, CD.ProductNumber, CD.OptionNumber)); //ResolveXY-functions return null, if no match is found in db.
|
|
|
|
// if (CD.Products == null)
|
|
// {
|
|
// CDsWithoutEFReferences.Add(CD);
|
|
// continue;
|
|
// }
|
|
|
|
// //Establish EF Reference. If no Supplier-Account found, then skip this custom description.
|
|
// CD.Supplier = ResolveAccountByName(db, CD.Supplier.AccountName); //ResolveXY-functions return null, if no match is found in db.
|
|
// if (CD.Supplier == null)
|
|
// {
|
|
// CDsWithoutEFReferences.Add(CD);
|
|
// continue;
|
|
// }
|
|
// _ = MetaDataSetter.ForImport(CD, "DocxImporter", "Initial import by CSV Importer (Function DbHelper.ImportCustomDescriptionsFromDocx)");
|
|
|
|
// //add to final list of CDs, that will go into the db.
|
|
// importedCDsWithEFReferences.Add(CD);
|
|
// }
|
|
|
|
// db.CustomDescriptions.AddRange(importedCDsWithEFReferences);
|
|
// _ = db.SaveChanges();
|
|
// }
|
|
// return true;
|
|
//}
|
|
|
|
private static bool UpdateProductsFromCsv(string filepath = "", string separator = "|", bool dataHasHeading = true) {
|
|
string fileName = ExtractFileName(filepath);
|
|
if (filepath == "") return false; //Wenn keine Datei ausgewählt (Cancel geklickt), dann Abbruch.
|
|
|
|
//Aktiven Produkte aus DB laden
|
|
using (GremlinDb gremlinDb = new()) {
|
|
//Aktive Produkte aus der DB einlesen
|
|
|
|
List<Product> activeProductsInDb = gremlinDb.Products.Where(p => p.DataStatus == Status.Active.ToString()).Include(p => p.ProductLine).ToList();
|
|
|
|
//Neue CPL einlesen...
|
|
List<Product> productsReadFromFile = new(ParseProductFile(filepath, separator, dataHasHeading));
|
|
|
|
//...Aufteilung in neue und nicht-neue Produkte...
|
|
List<Product> newProducts = new(FilterNewProducts(productsReadFromFile));
|
|
List<Product> nonNewProducts = new(productsReadFromFile.Except(newProducts));
|
|
|
|
//...Letztere wiederum in obsolete Produkte...
|
|
ProductEqualityComparer proEc = new();
|
|
List<Product> obsoleteProducts = new(activeProductsInDb.Except(nonNewProducts, proEc));
|
|
|
|
DateTime now = DateTime.Now;
|
|
|
|
//Obsolete Produkte prozessieren
|
|
foreach (Product product in obsoleteProducts) {
|
|
product.ProductStatus = Status.Obsolete.ToString();
|
|
product.DataStatus = Status.Archived.ToString();
|
|
product.DataValidUntil = now;
|
|
product.DataModificationDate = now;
|
|
product.DataModificationByUser = "CPL Updater";
|
|
}
|
|
|
|
//den Rest prozessieren
|
|
List<Product> updatedProducts = new(10000);
|
|
string dataVersionComment = "Data as per " + fileName;
|
|
|
|
////Counter für Debugging
|
|
//int x = 0;
|
|
|
|
//Multithreading
|
|
_ = Parallel.ForEach(nonNewProducts, parallelOptions, product => {
|
|
////Debugging-Counter
|
|
//x++;
|
|
|
|
Product? existingProduct = activeProductsInDb.FirstOrDefault(p => p.ProductNumber == product.ProductNumber && p.OptionNumber == product.OptionNumber && p.BreakRangeFrom == product.BreakRangeFrom && p.BreakRangeTo == product.BreakRangeTo);
|
|
|
|
//Checkpoint, falls ein neues Produkt versehentlich auf "Active" statt auf "New" gesetzt ist.
|
|
if (existingProduct == null) {
|
|
newProducts.Add(product);
|
|
return;
|
|
}
|
|
|
|
//Wenn keine Änderung, dann nur DataVersionComment mit CPL-Dateinamen aktualisieren...
|
|
|
|
if (product.ListPrice == existingProduct.ListPrice && product.ProductStatus == existingProduct.ProductStatus && Normalize(product.SapLongDescription) == Normalize(existingProduct.SapLongDescription) && Normalize(product.SapShortDescription) == Normalize(existingProduct.SapShortDescription)) {
|
|
existingProduct.DataVersionComment = dataVersionComment;
|
|
}
|
|
|
|
//andernfalls die vorhandene Datensatz-Version archivieren und neue Version anlegen
|
|
else //alten Datensatz archivieren:
|
|
{
|
|
existingProduct.DataStatus = Status.Archived.ToString();
|
|
existingProduct.DataModificationByUser = "CPL Updater";
|
|
existingProduct.DataModificationDate = now;
|
|
existingProduct.DataValidUntil = now;
|
|
existingProduct.DataVersionComment = "Archived b/c of data update";
|
|
|
|
if (product.ListPrice != existingProduct.ListPrice)
|
|
existingProduct.ProductStatus = Status.PriceUpdated.ToString();
|
|
else if (Normalize(product.SapLongDescription) != Normalize(existingProduct.SapLongDescription) || Normalize(product.SapShortDescription) != Normalize(existingProduct.SapShortDescription))
|
|
existingProduct.ProductStatus = Status.DescriptionUpdated.ToString();
|
|
else if (product.ProductStatus == existingProduct.ProductStatus) existingProduct.ProductStatus = Status.StatusUpdated.ToString();
|
|
|
|
//neuen Datensatz anlegen
|
|
Product updatedProduct = new() {
|
|
ProductNumber = product.ProductNumber,
|
|
OptionNumber = product.OptionNumber,
|
|
BreakRangeFrom = product.BreakRangeFrom,
|
|
BreakRangeTo = product.BreakRangeTo,
|
|
HasBreakPrices = product.HasBreakPrices,
|
|
IntroductionDate = existingProduct.IntroductionDate,
|
|
ListPrice = product.ListPrice,
|
|
ProductStatus = Status.Active.ToString(),
|
|
SapLongDescription = product.SapLongDescription,
|
|
SapShortDescription = product.SapShortDescription,
|
|
Weight = product.Weight
|
|
};
|
|
_ = MetaDataSetter.ForImport(updatedProduct, "CPL Updater", "Product Update");
|
|
|
|
updatedProduct.ProductLine = product.ProductLine.ProductLineCode == existingProduct.ProductLine.ProductLineCode ? product.ProductLine : ResolveProductLine(gremlinDb, product.ProductLine.ProductLineCode);
|
|
newProducts.Add(updatedProduct);
|
|
}
|
|
|
|
updatedProducts.Add(existingProduct);
|
|
});
|
|
|
|
_ = InsertProducts(newProducts); //enthält auch ResolvePL()
|
|
gremlinDb.Products.UpdateRange(obsoleteProducts);
|
|
gremlinDb.Products.UpdateRange(updatedProducts);
|
|
int changes = gremlinDb.SaveChanges();
|
|
Console.WriteLine($"Es wurden {changes} Änderungen an der Datenbank durchgeführt.\n Davon waren {updatedProducts.Count} UpdatedProducts, {obsoleteProducts.Count} ObsoleteProducts und {newProducts.Count} NewProducts");
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
private static Dictionary<string, int> ColumnMapping(string[] fields) {
|
|
Dictionary<string, int> result = new();
|
|
for (int i = 0; i < fields.Length; i++)
|
|
switch (fields[i].ToLower(CultureInfo.CurrentCulture).Trim().Replace(" ", "").Replace("-", "").Replace("_", "").Replace(".", "").Replace(":", "")) {
|
|
case "accountid" or "fcustomercd" or "sapaccountnumber":
|
|
result.Add("SAPAccountNumber", i);
|
|
break;
|
|
case "accountname" or "fcustomername":
|
|
result.Add("AccountName", i);
|
|
break;
|
|
case "postalcode" or "fpostcode" or "zip":
|
|
result.Add("ZIP", i);
|
|
break;
|
|
case "city" or "ftown":
|
|
result.Add("City", i);
|
|
break;
|
|
case "street" or "faddress":
|
|
result.Add("Street", i);
|
|
break;
|
|
case "title" or "ftitletext1":
|
|
result.Add("AcademicTitle", i);
|
|
break;
|
|
case "gender" or "fgender1":
|
|
result.Add("Gender", i);
|
|
break;
|
|
case "firstname" or "ffirstname":
|
|
result.Add("FirstName", i);
|
|
break;
|
|
case "lastname" or "flastname":
|
|
result.Add("LastName", i);
|
|
break;
|
|
case "optin" or "femailopt":
|
|
result.Add("OptInStatus", i);
|
|
break;
|
|
case "workemail" or "fworkemail1" or "accountemail":
|
|
result.Add("EMail", i);
|
|
break;
|
|
case "bouncedbackemail" or "fbouncedback":
|
|
result.Add("EmailBounced", i);
|
|
break;
|
|
case "department" or "fdepartment1":
|
|
result.Add("Department", i);
|
|
break;
|
|
case "roomnumber" or "froomnumber":
|
|
result.Add("Room", i);
|
|
break;
|
|
case "workphone" or "fworkphone1" or "phonenumber":
|
|
result.Add("PhoneNumber", i);
|
|
break;
|
|
case "faxnumber":
|
|
result.Add("FaxNumber", i);
|
|
break;
|
|
case "function" or "ffunction":
|
|
result.Add("Function", i);
|
|
break;
|
|
case "contactid" or "fcontactcd":
|
|
result.Add("SAPContactNumber", i);
|
|
break;
|
|
case "contactcreationdate" or "fcreationdate":
|
|
result.Add("SAPContactCreationDate", i);
|
|
break;
|
|
case "mobilephone" or "fmobilephone":
|
|
result.Add("MobileNumber", i);
|
|
break;
|
|
case "jobfunction" or "fjobfunction":
|
|
result.Add("MA_JobFunctions", i);
|
|
break;
|
|
case "productinterest" or "fproductinterest":
|
|
result.Add("MA_ProductInterests", i);
|
|
break;
|
|
case "applicationinterest" or "fapplicationinterest":
|
|
result.Add("MA_ApplicationInterests", i);
|
|
break;
|
|
case "joblevel" or "fjoblevel":
|
|
result.Add("MA_JobLevel", i);
|
|
break;
|
|
case "contactindustry" or "fcontactindustry":
|
|
result.Add("MA_ContactIndustry", i);
|
|
break;
|
|
case "competitiveibase" or "fcompetativeibase":
|
|
result.Add("MA_CompetitiveIBase", i);
|
|
break;
|
|
case "submarketcode" or "fsubmarketcd":
|
|
result.Add("SubMarketCode", i);
|
|
break;
|
|
case "customertypecode" or "fcustomertypecd" or "accounttype" or "accounttypecode":
|
|
result.Add("AccountTypeCode", i);
|
|
break;
|
|
case "phone" or "fphone":
|
|
result.Add("AccountPhoneNumber", i);
|
|
break;
|
|
case "accountcreatedon" or "fcreatedon":
|
|
result.Add("AccountCreatedInSAPOn", i);
|
|
break;
|
|
case "contactchangedon" or "fcontactchangedon":
|
|
result.Add("SAPContactModifiedDate", i);
|
|
break;
|
|
case "notelephonecalls" or "fnotelephonecalls":
|
|
result.Add("NoPhoneCalls", i);
|
|
break;
|
|
case "nohardcopymailing" or "fnohardcopymailing":
|
|
result.Add("NoHardcopyMailing", i);
|
|
break;
|
|
case "accounttypedescription":
|
|
result.Add("AccountTypeDescription", i);
|
|
break;
|
|
case "submarketdescription":
|
|
result.Add("SubMarketDescription", i);
|
|
break;
|
|
case "productlineabbreviation":
|
|
result.Add("ProductLineAbbreviation", i);
|
|
break;
|
|
case "productlinedescription":
|
|
result.Add("ProductLineDescription", i);
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private static List<Product> ParseProductFile(string filepath, string separator, bool dataHasHeading) {
|
|
List<Product> results = new(100000);
|
|
//ENCODING CHANGED TO ISO-8859-1 AS EQUIVALENT (?) TO "LATIN1" (unavailable). TO BE TESTED!
|
|
using TextFieldParser csvParser = new(filepath, FileService.GetEncoding(filepath));
|
|
//Parser configuration:
|
|
csvParser.Delimiters = new[] { separator };
|
|
csvParser.CommentTokens = new[] { "#" };
|
|
csvParser.HasFieldsEnclosedInQuotes = true;
|
|
|
|
// Skip the row with the column names:
|
|
if (dataHasHeading) _ = csvParser.ReadLine();
|
|
|
|
//decimal oldListPrice;
|
|
//bool listpriceHasChanged;
|
|
while (!csvParser.EndOfData) {
|
|
// Read current line fields, pointer moves to the next line.
|
|
Product importedProduct = new() { ProductLine = new() };
|
|
string[] fields = csvParser.ReadFields() ?? new string[1];
|
|
|
|
//Kontrolle, ob Trennzeichen in Daten vorhanden ist:
|
|
if (fields.Length > 27) //27 ist der Normalfall
|
|
//Sonderfall "EnVisionTM G|2":
|
|
//suche fields[x], das auf " G" endet und auf das field[x+1] mit "2 " beginnt, kombiniere die beiden und schiebe alle darauffolgenden Felder in diesem Datensatz eins nach links.
|
|
for (int i = 0; i < fields.Length - 1; i++) //fields.Length - 1, um durch i+1 nicht aus dem Index zu laufen
|
|
if (fields[i].EndsWith(" G"))
|
|
if (fields[i + 1].StartsWith("2 ")) {
|
|
fields[i] = fields[i] + fields[i + 1];
|
|
for (int j = i + 2; j < fields.Length; j++) fields[j - 1] = fields[j];
|
|
}
|
|
|
|
//NICHT ausgewertete Felder:
|
|
//fields[0] = Position [in CPL]
|
|
//fields[8] = Warranty
|
|
//fields[10] = PH Code
|
|
//fields[11] = PH Description
|
|
//fields[15] = Country of Manufacturing
|
|
//fields[16] = ECCL
|
|
//fields[17] = M41
|
|
//fields[18] = First Supplier Code
|
|
//fields[19] = Harmonized Tarif Schedule
|
|
//fields[20] = Hazardous Good Flag
|
|
//fields[21] = Order instructions
|
|
//fields[23] = End of Production Date
|
|
//fields[24] = End of Support Date
|
|
|
|
importedProduct.ProductNumber = fields[1];
|
|
|
|
importedProduct.OptionNumber = fields[2].Length switch {
|
|
//Optionsnummer mit führendem Apostroph
|
|
4 => fields[2][1..],
|
|
//3-stellige Optionsnummer übernehmen; keine Aktion bei leerem Feld (keine Optionsnummer)
|
|
3 => fields[2],
|
|
_ => importedProduct.OptionNumber
|
|
};
|
|
|
|
importedProduct.SapShortDescription = fields[3];
|
|
|
|
importedProduct.ListPrice = decimal.Parse(fields[4], new CultureInfo("de-de")); //parsing! compare with old value (either from CSV or from DB) -> price change?
|
|
|
|
//if (fields[5] != "")
|
|
// if (decimal.Parse(fields[5], new CultureInfo("de-de")) != ImportedProduct.ListPrice)
|
|
// listpriceHasChanged = true;
|
|
|
|
importedProduct.BreakRangeFrom = fields[6] == "" ? 0 : Convert.ToInt32(fields[6]);
|
|
importedProduct.HasBreakPrices = importedProduct.BreakRangeFrom > 0;
|
|
importedProduct.BreakRangeTo = fields[7] is "" or "+" ? 0 : Convert.ToInt32(fields[7]); //erfasst sowohl Produkte ohne Break-Preise ("") als auch "+" bei Mengenangaben a la "100+" (= von 100 bis unendlich)
|
|
|
|
importedProduct.ProductLine.ProductLineCode = fields[9];
|
|
|
|
switch (fields[12]) {
|
|
case "Active":
|
|
importedProduct.DataStatus = Status.Active.ToString();
|
|
importedProduct.ProductStatus = Status.Active.ToString();
|
|
break;
|
|
case "New Product" or "New":
|
|
importedProduct.DataStatus = Status.Active.ToString();
|
|
importedProduct.ProductStatus = Status.New.ToString();
|
|
break;
|
|
case "Price Changed":
|
|
importedProduct.DataStatus = Status.Active.ToString();
|
|
importedProduct.ProductStatus = Status.PriceUpdated.ToString();
|
|
break;
|
|
default:
|
|
importedProduct.DataStatus = Status.StatusUpdated.ToString();
|
|
break;
|
|
}
|
|
|
|
importedProduct.Weight = ParseWeight(fields[14]);
|
|
|
|
if (fields[13] == "G") importedProduct.Weight /= 1000; //Umrechnung g in kg
|
|
|
|
if (fields[22] != "") importedProduct.IntroductionDate = DateTime.Parse(fields[22]);
|
|
|
|
importedProduct.SapLongDescription = fields[25];
|
|
|
|
results.Add(importedProduct);
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
private static float ParseWeight(string input) {
|
|
StringBuilder sb = new();
|
|
if (input.StartsWith(".")) input = sb.Append(0).Append(input).ToString();
|
|
|
|
try {
|
|
return float.Parse(input, new CultureInfo("en-us"));
|
|
}
|
|
catch (Exception ex) {
|
|
Debug.WriteLine(ex, "Unhandled Error in Function 'ParseWeight'");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
private static bool InsertProducts(List<Product> products) {
|
|
using (GremlinDb gremlinDb = new()) {
|
|
List<ProductLine> productLines = gremlinDb.ProductLines.ToList();
|
|
|
|
foreach (Product product in products) {
|
|
product.ProductLine = productLines.Find(x => x.ProductLineCode == product.ProductLine.ProductLineCode) ?? new ProductLine();
|
|
|
|
_ = MetaDataSetter.ForImport(product, "CSVImporter", "Initial import by CSV Importer (Function DbHelper.ImportProductsFromCSV)");
|
|
}
|
|
|
|
|
|
gremlinDb.Products.AddRange(products);
|
|
|
|
_ = gremlinDb.SaveChanges();
|
|
//Bestätigung senden
|
|
// Console.WriteLine($"Es wurden {products.Count} Produkte erfolgreich der Datenbank hinzugefügt.");
|
|
Console.WriteLine($"Es wurden {products.Count} Produkte erfolgreich der Datenbank hinzugefügt.");
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public static void DisplayErrorDetails(Exception ex, string errorRaiser) {
|
|
Console.WriteLine($"Source: {ex.Source}{Environment.NewLine}" + $"Message: {ex.Message}{Environment.NewLine}{Environment.NewLine}" + $"Contact: {errorRaiser}");
|
|
}
|
|
|
|
private static string ExtractFileName(string filepath, bool withExtension = false) {
|
|
string[] fields = filepath.Split(@"\");
|
|
string[] filename = fields[^1].Split(".");
|
|
return withExtension ? fields[^1] : filename[0];
|
|
}
|
|
|
|
private static string Normalize(string input) {
|
|
return input.ToLower().Trim().Replace(" ", "").Replace("-", "").Replace("_", "").Replace(".", "");
|
|
}
|
|
|
|
private static List<Product> FilterNewProducts(List<Product> products) {
|
|
DateTime now = DateTime.Now;
|
|
|
|
List<Product> results = new(5000);
|
|
foreach (Product product in products)
|
|
if (product.ProductStatus == Status.New.ToString()) {
|
|
product.DataCreationDate = now;
|
|
product.DataModificationDate = now;
|
|
product.DataValidFrom = now;
|
|
product.DataValidUntil = farInTheFuture;
|
|
product.DataModificationByUser = "CPL Updater";
|
|
product.DataVersionNumber = 1;
|
|
product.DataVersionComment = "Initial Import by CSV Importer/Updater";
|
|
results.Add(product);
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
//private static List<Product> FilterProductsWithPriceChange(List<Product> products)
|
|
//{
|
|
// List<Product> results = new();
|
|
// foreach (var product in products)
|
|
// {
|
|
// if (product.ProductStatus == Status.PriceUpdated.ToString())
|
|
// {
|
|
// results.Add(product);
|
|
// }
|
|
// }
|
|
// return results;
|
|
//}
|
|
|
|
public static async Task<bool> ImportLsagContactListToolDataAsync() {
|
|
return await Task.Run(() => ImportLsagContactListToolData());
|
|
}
|
|
|
|
public static async Task<bool> ImportAccountsFromCsvAsync() {
|
|
return await Task.Run(() => ImportAccountsFromCsv());
|
|
}
|
|
|
|
public static async Task<bool> ImportContactsFromCsvAsync() {
|
|
return await Task.Run(() => ImportContactsFromCsv());
|
|
}
|
|
|
|
public static async Task<bool> ImportProductsFromCsvAsync() {
|
|
return await Task.Run(() => ImportProductsFromCsv());
|
|
}
|
|
|
|
//public static async Task<bool> ImportCustomDescriptionsFromDocxAsync() => await Task.Run(() => ImportCustomDescriptionsFromDocx());
|
|
|
|
public static async Task<bool> ImportCustomDescriptionsFromCsvAsync() {
|
|
return await Task.Run(() => ImportCustomDescriptionsFromCsv());
|
|
}
|
|
|
|
public static async Task<bool> UpdateProductsFromCsvAsync() {
|
|
return await Task.Run(() => UpdateProductsFromCsv());
|
|
}
|
|
|
|
public static Account ResolveAccountByName(GremlinDb db, string accountName) {
|
|
try {
|
|
return db.Accounts.Include(account => account.AccountType).Include(account => account.SubMarket).First(account => account.AccountName == accountName);
|
|
}
|
|
catch {
|
|
return new();
|
|
}
|
|
}
|
|
|
|
public static Account ResolveAccountById(GremlinDb db, uint accountId) {
|
|
try {
|
|
return db.Accounts.First(account => account.SapAccountNumber == accountId);
|
|
}
|
|
catch {
|
|
return new();
|
|
}
|
|
}
|
|
|
|
public static AccountType? ResolveAccountType(GremlinDb db, string accountTypeCode) {
|
|
try {
|
|
return db.AccountTypes.First(account => account.AccountTypeCode == accountTypeCode);
|
|
}
|
|
catch {
|
|
return new();
|
|
}
|
|
}
|
|
|
|
public static SubMarket ResolveSubmarket(GremlinDb db, string subMarketCode) {
|
|
try {
|
|
return db.SubMarkets.First(submarket => submarket.SubMarketCode == subMarketCode);
|
|
}
|
|
catch {
|
|
return new();
|
|
}
|
|
}
|
|
|
|
public static ProductLine ResolveProductLine(GremlinDb db, string productLineCode) {
|
|
try {
|
|
return db.ProductLines.First(productline => productline.ProductLineCode == productLineCode);
|
|
}
|
|
catch {
|
|
return new();
|
|
}
|
|
}
|
|
|
|
private static string RandomString(int length) {
|
|
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
return new(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray());
|
|
}
|
|
} |