diff --git a/Gremlin_BlazorServer/Data/EntityClasses/Account.cs b/Gremlin_BlazorServer/Data/EntityClasses/Account.cs index ec22605..139b863 100644 --- a/Gremlin_BlazorServer/Data/EntityClasses/Account.cs +++ b/Gremlin_BlazorServer/Data/EntityClasses/Account.cs @@ -52,53 +52,56 @@ public class Account : IMetadata //IBase //tbd - //public bool Equals(Account other) - //{ - // if (other == null) return false; - // if (this == null) return false; - // if (this.SAPAccountNumber == other.SAPAccountNumber) return true; - // else return false; - //} - - //public static bool operator ==(Account account1, Account account2) - //{ - // if (account1.SAPAccountNumber == 0) return false; - // if (account2.SAPAccountNumber == 0) return false; - // if (account1.SAPAccountNumber == account2.SAPAccountNumber) return true; - // else return false; - //} - - //public static bool operator !=(Account account1, Account account2) - //{ - // if (account1.SAPAccountNumber == 0) return false; - // if (account2.SAPAccountNumber == 0) return false; - // if (account1.SAPAccountNumber == account2.SAPAccountNumber) return false; - // else return true; - //} - - //public override bool Equals(object obj) - //{ - // if (obj == null) return false; + public bool Equals(Account? other) { + if (other is null) return false; + return SapAccountNumber == other.SapAccountNumber + && AccountName == other.AccountName + && City == other.City + && EMail == other.EMail + && PhoneNumber == other.PhoneNumber + && Street == other.Street + && Zip == other.Zip; + } - // Account accountObj = obj as Account; - // if (accountObj == null) return false; - // else return base.Equals(obj); - //} + public static bool operator ==(Account? account1, Account? account2) { + if (account1 is null || account2 is null) return false; + if (account1.SapAccountNumber == 0) return false; + if (account2.SapAccountNumber == 0) return false; + return account1.SapAccountNumber == account2.SapAccountNumber + && account1.AccountName == account2.AccountName + && account1.City == account2.City + && account1.EMail == account2.EMail + && account1.PhoneNumber == account2.PhoneNumber + && account1.Street == account2.Street + && account1.Zip == account2.Zip; + } - //public override int GetHashCode() - ///// - /////Returns the (unique) SAP Account ID. - ///// - //{ - // return Convert.ToInt32(this.SAPAccountNumber); - //} + public static bool operator !=(Account? account1, Account? account2) + { + if (account1 is null || account2 is null) return false; + if (account1.SapAccountNumber == 0) return false; + if (account2.SapAccountNumber == 0) return false; + return account1.SapAccountNumber != account2.SapAccountNumber + && account1.AccountName != account2.AccountName + && account1.City != account2.City + && account1.EMail != account2.EMail + && account1.PhoneNumber != account2.PhoneNumber + && account1.Street != account2.Street + && account1.Zip != account2.Zip; + + } + // public override bool Equals(object? obj) { + // if (obj == null) return false; + // return obj is Account && base.Equals(obj); + // } + // + // public override int GetHashCode() => $"{AccountName}:{City}:{Street}:{Zip}".GetHashCode(); + public List AddIfUniqueTo(List accounts) { if (accounts.Count > 0 && SapAccountNumber == accounts[^1].SapAccountNumber) return accounts; - foreach (Account account in accounts) - if (SapAccountNumber == account.SapAccountNumber) - return accounts; + if (accounts.Any(account => SapAccountNumber == account.SapAccountNumber)) return accounts; accounts.Add(this); return accounts; diff --git a/Gremlin_BlazorServer/Data/EntityClasses/Contact.cs b/Gremlin_BlazorServer/Data/EntityClasses/Contact.cs index ab7576c..19a7cd1 100644 --- a/Gremlin_BlazorServer/Data/EntityClasses/Contact.cs +++ b/Gremlin_BlazorServer/Data/EntityClasses/Contact.cs @@ -1,4 +1,6 @@ -namespace Gremlin_BlazorServer.Data.EntityClasses; +using Newtonsoft.Json; + +namespace Gremlin_BlazorServer.Data.EntityClasses; public class Contact : IMetadata { //primary key: @@ -51,4 +53,49 @@ public class Contact : IMetadata { public uint DataVersionNumber { get; set; } = 1; public string? DataVersionComment { get; set; } public string DataStatus { get; set; } = "Active"; + + public bool Equals(Contact? other) { + if (other is null) return false; + return SapContactNumber == other.SapContactNumber + && LastName == other.LastName + && FirstName == other.FirstName + && EMail == other.EMail + && PhoneNumber == other.PhoneNumber + && EmailBounced == other.EmailBounced + && OptInStatus == other.OptInStatus; + } + + public static bool operator ==(Contact? contact1, Contact? contact2) { + if (contact1 is null || contact2 is null) return false; + if (contact1.SapContactNumber == 0) return false; + if (contact2.SapContactNumber == 0) return false; + return contact1.SapContactNumber == contact2.SapContactNumber + && contact1.LastName == contact2.LastName + && contact1.FirstName == contact2.FirstName + && contact1.EMail == contact2.EMail + && contact1.PhoneNumber == contact2.PhoneNumber + && contact1.EmailBounced == contact2.EmailBounced + && contact1.OptInStatus == contact2.OptInStatus; + } + + public static bool operator !=(Contact? contact1, Contact? contact2) + { + if (contact1 is null || contact2 is null) return false; + if (contact1.SapContactNumber == 0) return false; + if (contact2.SapContactNumber == 0) return false; + return contact1.SapContactNumber != contact2.SapContactNumber + && contact1.LastName != contact2.LastName + && contact1.FirstName != contact2.FirstName + && contact1.EMail != contact2.EMail + && contact1.PhoneNumber != contact2.PhoneNumber + && contact1.EmailBounced != contact2.EmailBounced + && contact1.OptInStatus != contact2.OptInStatus; + } + + // public override bool Equals(object? obj) { + // if (obj == null) return false; + // return obj is Account && base.Equals(obj); + // } + // + // public override int GetHashCode() => $"{LastName}:{FirstName}:{EMail}".GetHashCode(); } \ No newline at end of file diff --git a/Gremlin_BlazorServer/Data/EntityClasses/IMetadata.cs b/Gremlin_BlazorServer/Data/EntityClasses/IMetadata.cs index c11e95e..0c30472 100644 --- a/Gremlin_BlazorServer/Data/EntityClasses/IMetadata.cs +++ b/Gremlin_BlazorServer/Data/EntityClasses/IMetadata.cs @@ -9,4 +9,5 @@ public interface IMetadata { DateTime DataValidUntil { get; set; } string? DataVersionComment { get; set; } uint DataVersionNumber { get; set; } + int HashCode => GetHashCode(); } \ No newline at end of file diff --git a/Gremlin_BlazorServer/Data/EntityClasses/Product.cs b/Gremlin_BlazorServer/Data/EntityClasses/Product.cs index d108fe9..99a0bf4 100644 --- a/Gremlin_BlazorServer/Data/EntityClasses/Product.cs +++ b/Gremlin_BlazorServer/Data/EntityClasses/Product.cs @@ -36,4 +36,40 @@ public class Product : IMetadata { public uint DataVersionNumber { get; set; } public string? DataVersionComment { get; set; } public string DataStatus { get; set; } = "Active"; + + public bool Equals(Product? other) { + if (other is null) return false; + return ProductNumber == other.ProductNumber + && OptionNumber == other.OptionNumber + && SapShortDescription == other.SapShortDescription + && SapLongDescription == other.SapLongDescription + && ListPrice == other.ListPrice; + } + + public static bool operator ==(Product? product1, Product? product2) { + if (product1 is null || product2 is null) return false; + return product1.ProductNumber == product2.ProductNumber + && product1.OptionNumber == product2.OptionNumber + && product1.SapShortDescription == product2.SapShortDescription + && product1.SapLongDescription == product2.SapLongDescription + && product1.ListPrice == product2.ListPrice; + } + + public static bool operator !=(Product? product1, Product? product2) + { + if (product1 is null || product2 is null) return false; + return product1.ProductNumber != product2.ProductNumber + && product1.OptionNumber != product2.OptionNumber + && product1.SapShortDescription != product2.SapShortDescription + && product1.SapLongDescription != product2.SapLongDescription + && product1.ListPrice != product2.ListPrice; + } + + // public override bool Equals(object? obj) { + // if (obj == null) return false; + // return obj is Account && base.Equals(obj); + // } + + // public override int GetHashCode() => $"{ProductNumber}:{OptionNumber}".GetHashCode(); + } \ No newline at end of file diff --git a/Gremlin_BlazorServer/Pages/Accounts.razor b/Gremlin_BlazorServer/Pages/Accounts.razor index e9fdbb3..b47321f 100644 --- a/Gremlin_BlazorServer/Pages/Accounts.razor +++ b/Gremlin_BlazorServer/Pages/Accounts.razor @@ -103,17 +103,16 @@ Padding="Padding.Is3" style="box-shadow: 10px 10px #343A40"> + + + + Import Accounts from CSV - - - - - diff --git a/Gremlin_BlazorServer/Pages/Accounts.razor.cs b/Gremlin_BlazorServer/Pages/Accounts.razor.cs index fad242c..ca8d8ec 100644 --- a/Gremlin_BlazorServer/Pages/Accounts.razor.cs +++ b/Gremlin_BlazorServer/Pages/Accounts.razor.cs @@ -84,4 +84,9 @@ public partial class Accounts { // newAccount.SubMarket = await GenericController.GetAsync(sM => sM.SubMarketCode.Equals("VEN")); return newAccount; } + + private static async Task OnRemoveDublicates() { + int i = await GenericController.RemoveDublicatesAsync(); + Console.WriteLine($"Removed {i} dublicates from Accounts."); + } } \ No newline at end of file diff --git a/Gremlin_BlazorServer/Pages/Contacts.razor b/Gremlin_BlazorServer/Pages/Contacts.razor index d870605..38c9066 100644 --- a/Gremlin_BlazorServer/Pages/Contacts.razor +++ b/Gremlin_BlazorServer/Pages/Contacts.razor @@ -144,6 +144,10 @@ Padding="Padding.Is3" style="box-shadow: 10px 10px #343A40"> + + + + Import Contacts from CSV diff --git a/Gremlin_BlazorServer/Pages/Contacts.razor.cs b/Gremlin_BlazorServer/Pages/Contacts.razor.cs index da4ef9d..cd18228 100644 --- a/Gremlin_BlazorServer/Pages/Contacts.razor.cs +++ b/Gremlin_BlazorServer/Pages/Contacts.razor.cs @@ -89,4 +89,9 @@ public partial class Contacts { StateHasChanged(); } + + private static async Task OnRemoveDublicates() { + int i = await GenericController.RemoveDublicatesAsync(); + Console.WriteLine($"Removed {i} dublicates from Contacts."); + } } \ No newline at end of file diff --git a/Gremlin_BlazorServer/Pages/Products.razor b/Gremlin_BlazorServer/Pages/Products.razor index 9536380..e0ab44e 100644 --- a/Gremlin_BlazorServer/Pages/Products.razor +++ b/Gremlin_BlazorServer/Pages/Products.razor @@ -98,7 +98,23 @@ } *@ - +
+ + + + + + Import Products from TSV + + + + + +
+
(cD => cD.ProductNumber.Equals(selectedProduct.ProductNumber) && cD.OptionNumber.Equals(selectedProduct.OptionNumber)); } + + private static async Task OnRemoveDublicates() { + int i = await GenericController.RemoveDublicatesAsync(); + Console.WriteLine($"Removed {i} dublicates from Products."); + } + + private async Task OnImportProducts(FileChangedEventArgs fileChangedEventArgs) { + try { + foreach (IFileEntry? file in fileChangedEventArgs.Files) { + using MemoryStream stream = new(); + await file.WriteToStreamAsync(stream); + _ = stream.Seek(0, SeekOrigin.Begin); + using StreamReader reader = new(stream); + string fileContent = await reader.ReadToEndAsync(); + GenericImporter.ImportCsv(fileContent); + } + } + catch (Exception exception) { + Console.WriteLine(exception.Message); + } + + StateHasChanged(); + } } \ No newline at end of file diff --git a/Gremlin_BlazorServer/Services/GenericController.cs b/Gremlin_BlazorServer/Services/GenericController.cs index 150111d..c7ecb5f 100644 --- a/Gremlin_BlazorServer/Services/GenericController.cs +++ b/Gremlin_BlazorServer/Services/GenericController.cs @@ -20,7 +20,7 @@ public class GenericController { } } - public IList? GetAll(Predicate search) where TResult : class, IMetadata { + public static IList? GetAll(Predicate search) where TResult : class, IMetadata { ArgumentNullException.ThrowIfNull(search); try { return gremlinDb.Set().AsEnumerable().Where(t => search(t)).ToList(); @@ -207,12 +207,12 @@ public class GenericController { return 0; } } - + private static void HandleConcurrencyExceptions(DbUpdateException ex) { Console.WriteLine($"!!! HandleConcurrencyException: {ex.Message}"); - foreach (EntityEntry entry in ex.Entries) { + foreach (EntityEntry entry in ex.Entries) switch (entry.Entity) { - case Quote or CustomDescription or Account or Contact: { + case Quote or CustomDescription or Account or Contact or Product: { PropertyValues proposedValues = entry.CurrentValues; PropertyValues? databaseValues = entry.GetDatabaseValues(); @@ -230,6 +230,18 @@ public class GenericController { default: throw new NotSupportedException("Don't know how to handle concurrency conflicts for " + entry.Metadata.Name); } + } + + + public static async Task RemoveDublicatesAsync() where T : class, IMetadata { + try { + List entities = gremlinDb.Set().AsEnumerable().GroupBy(e => new { e.HashCode}).SelectMany(grp => grp.Skip(1)).ToList(); + gremlinDb.Set().RemoveRange(entities); + return await gremlinDb.SaveChangesAsync(); + } + catch (Exception exception) { + Console.WriteLine(exception.InnerException); + return 0; } } } \ No newline at end of file diff --git a/Gremlin_BlazorServer/Services/GenericImporter.cs b/Gremlin_BlazorServer/Services/GenericImporter.cs index e308661..e1619d2 100644 --- a/Gremlin_BlazorServer/Services/GenericImporter.cs +++ b/Gremlin_BlazorServer/Services/GenericImporter.cs @@ -6,12 +6,13 @@ using MySqlX.XDevAPI.Common; namespace Gremlin_BlazorServer.Services; public class GenericImporter { - - public static void ImportCsv(string fileContent) where T : class, IMetadata, new() { + + public static async void ImportCsv(string fileContent) where T : class, IMetadata, new() { Console.WriteLine($"GENERIC IMPORTER: Importing {typeof(T)} from csv..."); List splitLines = SplitLines(fileContent); Console.WriteLine($"Found {splitLines.Count} potential {typeof(T)} in csv."); - Console.WriteLine(ParseLinesToResultSet(splitLines) ? $"GENERIC IMPORTER: Ready." : $"GENERIC IMPORTER: Error by writing to db!"); + int i = await ParseLinesToResultSet(splitLines); + Console.WriteLine(i > 0 ? $"GENERIC IMPORTER: wrote {i} to db." : "GENERIC IMPORTER: Error by writing to db!"); } private static List SplitLines(string fileContent) { @@ -20,33 +21,75 @@ public class GenericImporter { return fileList; } - private static bool ParseLinesToResultSet(IEnumerable lineList) where T : class, IMetadata, new() { + private static void DrawTextProgressBar(int progress, int total) + { + //draw empty progress bar + Console.CursorLeft = 0; + Console.Write("["); //start + Console.CursorLeft = 64; + Console.Write("]"); //end + Console.CursorLeft = 1; + float onechunk = 62.0f / total; + + //draw filled part + int position = 1; + for (int i = 0; i < onechunk * progress; i++) + { + Console.BackgroundColor = ConsoleColor.Green; + Console.CursorLeft = position++; + Console.Write(" "); + } + + //draw unfilled part + for (int i = position; i <= 63 ; i++) + { + Console.BackgroundColor = ConsoleColor.Gray; + Console.CursorLeft = position++; + Console.Write(" "); + } + + //draw totals + Console.CursorLeft = 66; + Console.BackgroundColor = ConsoleColor.Black; + int percent = (int)MathF.Round((float)progress / total * 100, 0); + Console.Write($"{progress} of {total} [{percent}%] "); //blanks at the end remove any excess + } + private static async Task ParseLinesToResultSet(IEnumerable lineList) where T : class, IMetadata, new() { Tuple? resultSet = new(new(), new()); List updatedItems = new(); List newItems = new(); + IList? allItems = await GenericController.GetAllAsync(); + if (allItems is null) return 0; + int i = 0; - foreach (string[] line in lineList.Select(strings => strings.Select(x => x.Replace("\"", string.Empty)).ToArray())) { // Delete all "" - if (typeof(T) == typeof(Account)) resultSet = ParseToAccount(line) as Tuple; - if (typeof(T) == typeof(Contact)) resultSet = ParseToContact(line) as Tuple; + IEnumerable lines = lineList.Select(strings => strings.Select(x => x.Replace("\"", string.Empty)).ToArray()).ToList(); + foreach (string[] line in lines) { + i++; + if (typeof(T) == typeof(Account)) resultSet = ParseToAccount(line, allItems as IList) as Tuple; + if (typeof(T) == typeof(Contact)) resultSet = ParseToContact(line, allItems as IList) as Tuple; + if (typeof(T) == typeof(Product)) resultSet = ParseToProduct(line, allItems as IList) as Tuple; if (resultSet is null) continue; if (resultSet.Item1 is not null) updatedItems.Add(resultSet.Item1); if (resultSet.Item2 is not null) newItems.Add(resultSet.Item2); + DrawTextProgressBar(i, lines.Count()); } int success = 0; + Console.WriteLine(); Console.WriteLine($"Found {updatedItems.Count} updates and {newItems.Count} new items."); if (updatedItems.Count > 0) success += GenericController.Update(updatedItems); if (newItems.Count > 0) success += GenericController.Insert(newItems); - - return success > 0; + + return success; } - private static Tuple? ParseToAccount(IReadOnlyList line) { // "ID" "Name" "Street" "City" "BP Role" "Postal Code" "Customer Type" "Market Indicator" "Phone" "E-Mail" "Market code" + private static Tuple? ParseToAccount(IReadOnlyList line, IEnumerable allAccounts) { + // "ID" "Name" "Street" "City" "BP Role" "Postal Code" "Customer Type" "Market Indicator" "Phone" "E-Mail" "Market code" Account? updatedAccount = null; Account? newAccount = null; - + 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 @@ -56,8 +99,8 @@ public class GenericImporter { string subMarketCode = line[7]; if (subMarketCode is "" or null) subMarketCode = "CCH"; // standard AccountType - - Account readAccount = new() { + + Account readAccount = new(){ SapAccountNumber = sapAccountNumber, AccountName = line[1], //System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(line[1].ToLower()) Street = line[2], @@ -69,45 +112,45 @@ public class GenericImporter { AccountTypeCode = accountTypeCode, SubMarketCode = subMarketCode }; - - Account? existingAccount = GenericController.Get(a => a.SapAccountNumber == sapAccountNumber || a.AccountName == readAccount.AccountName); - + + Account? existingAccount = allAccounts.FirstOrDefault(a => a.SapAccountNumber == sapAccountNumber || a.AccountName == readAccount.AccountName); if (existingAccount is not null) { - if (IsEqualAccount(readAccount, existingAccount)) return null; + if (existingAccount.Equals(readAccount)) 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; + if (existingAccount.AccountName != readAccount.AccountName) existingAccount.AccountName = readAccount.AccountName; + if (existingAccount.City != readAccount.City) existingAccount.City = readAccount.City; + if (existingAccount.EMail != readAccount.EMail) existingAccount.EMail = readAccount.EMail; + if (existingAccount.PhoneNumber != readAccount.PhoneNumber) existingAccount.PhoneNumber = readAccount.PhoneNumber; + if (existingAccount.Street != readAccount.Street) existingAccount.Street = readAccount.Street; + if (existingAccount.Zip != readAccount.Zip) existingAccount.Zip = readAccount.Zip; + // Console.WriteLine($"Update in Contact {existingAccount.SapAccountNumber}:{existingAccount.AccountName}"); updatedAccount = existingAccount; } else { - Console.WriteLine($"Account {readAccount.SapAccountNumber}:{readAccount.AccountName} ist neu!"); + // Console.WriteLine($"Account {readAccount.SapAccountNumber}:{readAccount.AccountName} ist neu!"); newAccount = readAccount; } - + return new(updatedAccount, newAccount); } - - private static Tuple? ParseToContact(IReadOnlyList 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" + + private static Tuple? ParseToContact(IReadOnlyList line, IEnumerable allContacts) { + //"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" Contact? updatedContact = null; Contact? newContact = null; - + 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(a => a.SapAccountNumber.Equals(sapAccountNumber)); - if (account is null) { - Console.WriteLine($"Account with SapAccountNumber {sapAccountNumber} is not existing!!"); + if (account is null) + // Console.WriteLine($"Account with SapAccountNumber {sapAccountNumber} is not existing!!"); return null; //HACK: skip empty Accounts - } - Contact readContact = new() { + Contact readContact = new(){ SapContactNumber = sapContactNumber, AccountId = account.AccountId, LastName = System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(line[2].ToLower()), @@ -119,15 +162,10 @@ public class GenericImporter { DataModificationByUser = "Gremlin Generic Importer", Gender = 0 }; - - Contact? existingContact = GenericController.Get(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; - } + Contact? existingContact = allContacts.FirstOrDefault(a => a.SapContactNumber == sapContactNumber || (a.LastName == readContact.LastName && a.FirstName == readContact.FirstName)); + if (existingContact is not null) { + if (existingContact.Equals(readContact)) return null; existingContact.DataModificationDate = DateTime.Now; existingContact.DataVersionNumber++; existingContact.DataModificationByUser = "Updated by Gremlin Generic Importer"; @@ -137,57 +175,63 @@ public class GenericImporter { existingContact.PhoneNumber = readContact.PhoneNumber; existingContact.EmailBounced = readContact.EmailBounced; existingContact.OptInStatus = readContact.OptInStatus; - Console.WriteLine($"Update in Contact {existingContact.SapContactNumber}:{existingContact.FirstName} {existingContact.LastName}"); + // Console.WriteLine($"Update in Contact {existingContact.SapContactNumber}:{existingContact.FirstName} {existingContact.LastName}"); updatedContact = existingContact; } else { - Console.WriteLine($"Contact {readContact.SapContactNumber}:{readContact.FirstName} {readContact.LastName} ist neu!"); + // Console.WriteLine($"Contact {readContact.SapContactNumber}:{readContact.FirstName} {readContact.LastName} ist neu!"); newContact = readContact; } return new(updatedContact, newContact); } - private static bool IsEqualAccount(Account readAccount, Account existingAccount) { - bool equalAccount = true; - if (readAccount.AccountName != existingAccount.AccountName) { - equalAccount = false; - Console.WriteLine($"--- UPDATE in Account {readAccount.SapAccountNumber} ---"); - Console.WriteLine($"{readAccount.AccountName} | {existingAccount.AccountName}"); - } - if (readAccount.City != existingAccount.City) { - equalAccount = false; - Console.WriteLine($"--- UPDATE in Account {readAccount.SapAccountNumber} ---"); - Console.WriteLine($"{readAccount.City} | {existingAccount.City}"); - } - if (readAccount.EMail != existingAccount.EMail) { - equalAccount = false; - 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}"); + private static Tuple? ParseToProduct(IReadOnlyList line, IEnumerable allProducts) { + //Position Partnumber Option Description Current Month Price(EUR) Previous Month Price(EUR) Breaks Range From Breaks Range To Warranty Productline PH Code PH Description Status Air Packaged Unit Air Packaged Weight Country of Manufacturing ECCL M41 First Supplier code Harmonized Tarif Schedule Hazardous Goods Flag Order Instructions Introduction Date End of Production Date End of Support Date Long Description + Product? updatedProduct = null; + Product? newProduct = null; + + if (line[0].Contains("Position")) return null; //HACK: skip first row if header + if (!decimal.TryParse(line[4], out decimal listPrice)) return null; //ListPrice not convertable + if (!int.TryParse(line[6], out int breakRangeFrom)) breakRangeFrom = 0; //no BreakRangeFrom + if (!int.TryParse(line[7], out int breakRangeTo)) breakRangeTo = 0; //no BreakRangeTo + if (!float.TryParse(line[13], out float weight)) weight = 0; //no Weight + + Product readProduct = new(){ + ProductNumber = line[1], + OptionNumber = line[2].Replace("'", ""), + SapShortDescription = line[3], + ListPrice = listPrice, + ProductLineCode = line[9], + SapLongDescription = line[25], + BreakRangeFrom = breakRangeFrom, + BreakRangeTo = breakRangeTo, + Weight = weight, + DataModificationByUser = "Gremlin Generic Importer", + }; + + Product? existingProduct = allProducts.FirstOrDefault(p => p.ProductNumber.Equals(readProduct.ProductNumber) && p.OptionNumber.Equals(readProduct.OptionNumber)); + if (existingProduct is not null) { + if (existingProduct.Equals(readProduct)) return null; + existingProduct.DataModificationDate = DateTime.Now; + existingProduct.DataVersionNumber++; + existingProduct.DataModificationByUser = "Updated by Gremlin Generic Importer"; + existingProduct.SapShortDescription = readProduct.SapShortDescription; + existingProduct.ListPrice = readProduct.ListPrice; + existingProduct.ProductLine = readProduct.ProductLine; + existingProduct.SapLongDescription = readProduct.SapLongDescription; + existingProduct.BreakRangeFrom = readProduct.BreakRangeFrom; + existingProduct.BreakRangeTo = readProduct.BreakRangeTo; + existingProduct.HasBreakPrices = existingProduct.BreakRangeFrom != 0 || existingProduct.BreakRangeTo != 0; + existingProduct.Weight = readProduct.Weight; + // Console.WriteLine($"Update in Product {existingProduct.ProductNumber}#{existingProduct.OptionNumber}:{existingProduct.SapShortDescription}"); + updatedProduct = existingProduct; } - if (readAccount.Zip != existingAccount.Zip) { - equalAccount = false; - Console.WriteLine($"--- UPDATE in Account {readAccount.SapAccountNumber} ---"); - Console.WriteLine($"{readAccount.Zip} | {existingAccount.Zip}"); + else { + // Console.WriteLine($"Product {readProduct.ProductNumber}#{readProduct.OptionNumber}:{readProduct.SapShortDescription} ist neu!"); + newProduct = readProduct; } - return equalAccount; - } - private static bool IsEqualContact(Contact readContact, Contact existingContact) - => readContact.LastName == existingContact.LastName - && readContact.FirstName == existingContact.FirstName - && readContact.EMail == existingContact.EMail - && readContact.PhoneNumber == existingContact.PhoneNumber - && readContact.EmailBounced == existingContact.EmailBounced - && readContact.OptInStatus == existingContact.OptInStatus; + return new(updatedProduct, newProduct); + } } \ No newline at end of file diff --git a/Gremlin_BlazorServer/wwwroot/quotes/Advanced_Accelerator_Applications_Germany_GmbH/2023-8-Battenberg-8890GC/DE-83PE89-823-271.pdf b/Gremlin_BlazorServer/wwwroot/quotes/Advanced_Accelerator_Applications_Germany_GmbH/2023-8-Battenberg-8890GC/DE-83PE89-823-271.pdf new file mode 100644 index 0000000..edac8ce Binary files /dev/null and b/Gremlin_BlazorServer/wwwroot/quotes/Advanced_Accelerator_Applications_Germany_GmbH/2023-8-Battenberg-8890GC/DE-83PE89-823-271.pdf differ diff --git a/Gremlin_BlazorServer/wwwroot/quotes/Advanced_Accelerator_Applications_Germany_GmbH/2023-8-Battenberg-8890GC/DE-83PE89-823-271.tex b/Gremlin_BlazorServer/wwwroot/quotes/Advanced_Accelerator_Applications_Germany_GmbH/2023-8-Battenberg-8890GC/DE-83PE89-823-271.tex new file mode 100644 index 0000000..d7606ed --- /dev/null +++ b/Gremlin_BlazorServer/wwwroot/quotes/Advanced_Accelerator_Applications_Germany_GmbH/2023-8-Battenberg-8890GC/DE-83PE89-823-271.tex @@ -0,0 +1,137 @@ +\documentclass[a4paper,ngerman,parskip,10pt]{scrlttr2} +\usepackage{lmodern} +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} +\usepackage{babel} +\usepackage[hidelinks]{hyperref} +\usepackage[left=2cm, right=2cm, top=2cm, bottom=2cm]{geometry} + +\usepackage[table]{xcolor} +\usepackage[right]{{eurosym}} +\usepackage[locale=DE]{{siunitx}} +\usepackage{{scrlayer-scrpage}} +\usepackage{{lastpage}} +\usepackage{{graphicx}} +\usepackage{{multirow}} +\usepackage{{longtable}} +\usepackage{{enumitem}} +\usepackage{{fp, xstring, spreadtab, numprint}} +\DeclareSIUnit{{\sieuro}}{{\mbox{{\euro}}}} +\rohead{DE-83PE89-823-271} +\cfoot{Seite \thepage/\pageref{LastPage}} +\sisetup{round-integer-to-decimal,round-precision=2,round-mode=places} +\newcommand{\produkttitel}[1]{\textsc{#1}} +\renewcommand{\arraystretch}{1.2} +\definecolor{AgilentBlau}{HTML}{0085d5} +\setlist{noitemsep} +\begin{document} +\begin{tabular}{p{0.4\hsize}p{0.5\hsize}} +\multirow{4}{*}{\includegraphics[width=0.9\hsize]{agilentLogo.png}} +&\normalsize{Agilent Technologies Deutschland GmbH}\\ +&\normalsize{Life Sciences \& Chemical Analysis}\\ +&\normalsize{Hewlett-Packard-Str. 8}\\ +&\normalsize{D-76337 Waldbronn} +\end{tabular} +\par +\begin{flushright} + +\colorbox{AgilentBlau}{\textcolor{white}{\textsc{\Huge{Angebot}}}} +\end{flushright} +\begin{tabular}{p{0.4\hsize}p{0.6\hsize}} + + & +\multirow{4}{*}{ +\begin{tabular}{|ll|} +\hline +\textbf{Angebotsnummer:}&DE-83PE89-823-271\\ +Angebotdatum:&\today\\ +Angebotsgültigkeit:&60 Tage\\\textbf{Ansprechpartner:}&Sascha Woitschetzki\\ +Telefon: &+49 208 74129134\\ +Mobil:&+49 163 9681131\\ +E-Mail:&\href{mailto:sascha.woitschetzki@non.agilent.com}{sascha.woitschetzki@non.agilent.com}\\ +\textbf{Auftragsannahme:}&\href{mailto:salesservices\_germany@agilent.com}{salesservices\_germany@agilent.com}\\ +\hline +\end{tabular} +}\\ +Herr Marcel Battenberg +\\ +Advanced Accelerator Applications Germany GmbH +\\ +Saime Genc Ring 18 +\\ +53121 Bonn +\\ +&\\ +&\\ +\end{tabular} +\vspace{1cm}\par +Sehr geehrter Herr Battenberg,\par +nachfolgend erhalten Sie Ihr gewünschtes Angebot über ein(e) 8890GC.\\ +Es umfasst im Einzelnen: +\begin{itemize} +\item 8890 Gaschromatograph (\#1) +\begin{itemize} +\item S/SL-Einlass (\#2) +\item Flammenionisationsdetektor (\#3) +\end{itemize} +\item DB-624 UI (\#4) +\item 8890 GC (\#5) +\begin{itemize} +\item Installation and Operational Qualification (\#6) +\end{itemize} +\end{itemize} +Für Rückfragen und Änderungswünsche stehe ich Ihnen gerne zur Verfügung.\par +Mit freundlichen Grüßen\\ +\includegraphics[width = 5cm]{signWoitschetzki.png} +\vspace{1cm} \\ + +\begin{center} +\begin{longtable} +{| cp{0.71\textwidth} cr |} \hline +\textbf{\#} & \textbf{Produktbeschreibung} (Produktnummer) & \textbf{Menge} & \textbf{Preis}\\ \hline \endhead +1 &\textbf{8890 Gaschromatograph} (G3540A)\newline Agilent 8890 GC\newline Ofen bis 450 °C, Kühlen von 450 auf 50 °C in unter 4 Min., bis zu 2 Inlets und 4 Detektoren. Elektronische Druck- und Flusskontrolle (EPC; 0-99 psi, 0.001 psi Genauigkeit), retention time locking (RTL).&1&\SI{8569.13}{\sieuro}\\ +2 &\textbf{S/SL-Einlass} (G3540A\#112)\newline Split/Splitless-Einlasssystem für Kapillarsäulen mit elektronischer Drucksteuerung (EPC), max. 100 psi.&1&\SI{2175.91}{\sieuro}\\ +3 &\textbf{Flammenionisationsdetektor} (G3540A\#211)\newline Flammenionisationsdetektor mit elektronischer Fluss- /Drucksteuerung zur digitalen Steuerung aller Detektorgase. Optimiert für Kapillarsäulen.&1&\SI{2167.45}{\sieuro}\\ +4 &\textbf{DB-624 UI} (123-1334UI)\newline 30m, 0.32 mm, 1.80 µm&2&\SI{761.4}{\sieuro}\\ +5 &\textbf{8890 GC} (SYS-GC-8890)\newline &1&\SI{0}{\sieuro}\\ +6 &\textbf{Installation and Operational Qualification} (SYS-GC-8890\#6H9)\newline Gerätequalifizierung (IQ/OQ) im Rahmen der Installation.&1&\SI{4088.7}{\sieuro}\\ +\hline +\end{longtable} +\end{center} + +\vspace{-2cm} +\begin{flushright} + +\begin{tabular}{|rr|} +\hline +\textbf{Summe netto} & \SI{17762.59}{\sieuro}\\ +\textbf{Versand und Bereitstellungskosten (3\%)} & \SI{532.8777}{\sieuro}\\ +\textbf{Gesamtsumme netto} & \SI{18295.4677}{\sieuro}\\ +\hline +\end{tabular} + +\end{flushright} + +Der Betrag versteht sich zzgl. der gesetzlichen Steuern.\\ +Diese werden im Rechnungszeitraum auf der Rechnung gesondert ausgewiesen.\\ +Zahlungsbedingungen: 30 Tage netto ab Rechnungsdatum.\\ +Incoterm (2010) für Lieferungen innerhalb Deutschlands: DDP. +\begin{small} + +\textbf{Gewährleistung:}\\ +Die Gewährleistung für Zubehör und Ersatzteilprodukte und für Analytik-Hardwareprodukte beträgt 12 Monate. + +\textbf{Hinweis:}\\ +Für den Verkauf der in diesem Angebot aufgeführten Standard-Produkte und -Services gelten die aktuellen \emph{Agilent Geschäftsbedingungen} und alle sonstigen anwendbaren Zusatzbedingungen sowie zusätzliche Bedingungen, soweit darauf hier Bezug genommen wird. Soweit Produkte oder Services nach speziellen Kundenanforderungen hergestellt, konfiguriert oder angepasst werden, gelten für den Verkauf aller in diesem Angebot aufgeführten Produkte und Services die aktuellen \emph{Agilent Geschäftsbedingungen für kundenspezifische Produkte} und alle sonstigen anwendbaren Zusatzbedingungen sowie zusätzliche Bedingungen, soweit darauf hier Bezug genommen wird. Eine Kopie der maßgeblichen Bedingungen ist entweder beigefügt oder wurde Ihnen bereits zur Verfügung gestellt. Sollten Sie keine Kopie erhalten haben oder eine weitere Kopie benötigen, setzen Sie sich bitte mit uns in Verbindung. Soweit Sie mit Agilent eine gesonderte Vereinbarung getroffen haben, die den Verkauf der in diesem Angebot aufgeführten Produkte und Services umfasst, sind die Bestimmungen dieser Vereinbarung anwendbar. Abweichende oder ergänzende Vereinbarungen, insbesondere widersprechende Geschäftsbedingungen, sind nur gültig, wenn sie ausdrücklich schriftlich vereinbart worden sind. Die angegebenen Daten zur Verfügbarkeit von Produkten und Services sind vorläufig. Die tatsächlichen Lieferzeiten bzw. Lieferperioden werden Ihnen bei Auftragsbestätigung mitgeteilt. Waren, Technologien oder Software, die aus den Vereinigten Staaten von Amerika (\emph{USA}) oder anderen exportierenden Ländern ausgeführt werden, unterliegen den Ausfuhrbestimmungen der USA sowie anderer Rechtsordnungen. Bei Ausfuhr ist der Kunde dafür verantwortlich, dass die anwendbaren Ausfuhrbestimmungen eingehalten werden. +\end{small} + +\begin{scriptsize} +Agilent Technologies Deutschland GmbH, Hewlett-Packard-Str. 8, D-76337 Waldbronn\\ +Telefon +49 (0)7243-602-0\\ +USt.-IdNr.: DE812729296, WEEE-Reg.-Nr. DE 86631749\\ +Sitz der Gesellschaft: Waldbronn – Amtsgericht Mannheim, HRB 723782\\ +Geschäftsführer: Dr. Andreas Kistner (Vorsitzender der Geschäftsführung), Armin Jehle, Norbert Sabatzki, Dr. Knut Wintergerst\\ +\href{www.agilent.com}{www.agilent.com} +\end{scriptsize} +\end{document} + diff --git a/Gremlin_BlazorServer/wwwroot/quotes/Advanced_Accelerator_Applications_Germany_GmbH/2023-8-Battenberg-8890GC/DE-83PE89-823-271.tsv b/Gremlin_BlazorServer/wwwroot/quotes/Advanced_Accelerator_Applications_Germany_GmbH/2023-8-Battenberg-8890GC/DE-83PE89-823-271.tsv new file mode 100644 index 0000000..49cba51 --- /dev/null +++ b/Gremlin_BlazorServer/wwwroot/quotes/Advanced_Accelerator_Applications_Germany_GmbH/2023-8-Battenberg-8890GC/DE-83PE89-823-271.tsv @@ -0,0 +1,7 @@ +# Part Number Opt PL Description Qty Price EUR Breaks EUR Uplift % Total Discount % Net EUR Total EUR Sales Discount YA9% Contractual Discount Y99% Promotion Discount Y07% Demo Discount Y04% PH Code PH Description YMax +1 G3540A AZ Agilent 8890 GC-System Kundenspezifisch 1 20258 0 0 57.7 8569.13 8569.13 57.7 0 0 0 ISG100G111 6890 GC system +2 G3540A 112 AZ 8890 100 psi Split/Splitless-Einlasszub. 1 5144 0 0 57.7 2175.91 2175.91 57.7 0 0 0 +3 G3540A 211 AZ 8890 FID Zubeh. optimiert f. Kapillare 1 5124 0 0 57.7 2167.45 2167.45 57.7 0 0 0 +4 123-1334UI JW DB-624 UI 30m, 0.32mm, 1.80u 2 900 0 0 57.7 380.7 761.4 57.7 0 0 0 CSCG25C25V SpecApps Volatile +5 SYS-GC-8890 74 8890 GC-System 1 0 0 0 30 0 0 30 0 0 0 TSSYS0SYGC Service Systems - Gas Chromatography > 29 +6 SYS-GC-8890 6H9 74 Analysegeraet-Qualifizierung-auf Wunsch 1 5841 0 0 30 4088.7 4088.7 30 0 0 0 TSSYS1 Serviced As Systems - 1 YR > 29 diff --git a/Gremlin_BlazorServer/wwwroot/quotes/Grünenthal_GmbH/2023-8-Ritter-GCMSD/DE-83PE89-823-269.pdf b/Gremlin_BlazorServer/wwwroot/quotes/Grünenthal_GmbH/2023-8-Ritter-GCMSD/DE-83PE89-823-269.pdf new file mode 100644 index 0000000..be69832 Binary files /dev/null and b/Gremlin_BlazorServer/wwwroot/quotes/Grünenthal_GmbH/2023-8-Ritter-GCMSD/DE-83PE89-823-269.pdf differ diff --git a/Gremlin_BlazorServer/wwwroot/quotes/Grünenthal_GmbH/2023-8-Ritter-GCMSD/DE-83PE89-823-269.tex b/Gremlin_BlazorServer/wwwroot/quotes/Grünenthal_GmbH/2023-8-Ritter-GCMSD/DE-83PE89-823-269.tex new file mode 100644 index 0000000..31cfc7c --- /dev/null +++ b/Gremlin_BlazorServer/wwwroot/quotes/Grünenthal_GmbH/2023-8-Ritter-GCMSD/DE-83PE89-823-269.tex @@ -0,0 +1,129 @@ +\documentclass[a4paper,ngerman,parskip,10pt]{scrlttr2} +\usepackage{lmodern} +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} +\usepackage{babel} +\usepackage[hidelinks]{hyperref} +\usepackage[left=2cm, right=2cm, top=2cm, bottom=2cm]{geometry} + +\usepackage[table]{xcolor} +\usepackage[right]{{eurosym}} +\usepackage[locale=DE]{{siunitx}} +\usepackage{{scrlayer-scrpage}} +\usepackage{{lastpage}} +\usepackage{{graphicx}} +\usepackage{{multirow}} +\usepackage{{longtable}} +\usepackage{{enumitem}} +\usepackage{{fp, xstring, spreadtab, numprint}} +\DeclareSIUnit{{\sieuro}}{{\mbox{{\euro}}}} +\rohead{DE-83PE89-823-269} +\cfoot{Seite \thepage/\pageref{LastPage}} +\sisetup{round-integer-to-decimal,round-precision=2,round-mode=places} +\newcommand{\produkttitel}[1]{\textsc{#1}} +\renewcommand{\arraystretch}{1.2} +\definecolor{AgilentBlau}{HTML}{0085d5} +\setlist{noitemsep} +\begin{document} +\begin{tabular}{p{0.4\hsize}p{0.5\hsize}} +\multirow{4}{*}{\includegraphics[width=0.9\hsize]{agilentLogo.png}} +&\normalsize{Agilent Technologies Deutschland GmbH}\\ +&\normalsize{Life Sciences \& Chemical Analysis}\\ +&\normalsize{Hewlett-Packard-Str. 8}\\ +&\normalsize{D-76337 Waldbronn} +\end{tabular} +\par +\begin{flushright} + +\colorbox{AgilentBlau}{\textcolor{white}{\textsc{\Huge{Angebot}}}} +\end{flushright} +\begin{tabular}{p{0.4\hsize}p{0.6\hsize}} + + & +\multirow{4}{*}{ +\begin{tabular}{|ll|} +\hline +\textbf{Angebotsnummer:}&DE-83PE89-823-269\\ +Angebotdatum:&\today\\ +Angebotsgültigkeit:&60 Tage\\\textbf{Ansprechpartner:}&Sascha Woitschetzki\\ +Telefon: &+49 208 74129134\\ +Mobil:&+49 163 9681131\\ +E-Mail:&\href{mailto:sascha.woitschetzki@non.agilent.com}{sascha.woitschetzki@non.agilent.com}\\ +\textbf{Auftragsannahme:}&\href{mailto:salesservices\_germany@agilent.com}{salesservices\_germany@agilent.com}\\ +\hline +\end{tabular} +}\\ +Frau Stefanie Ritter +\\ +Grünenthal GmbH +\\ +Zieglerstr. 6 +\\ +52224 Stolberg +\\ +&\\ +&\\ +\end{tabular} +\vspace{1cm}\par +Sehr geehrte Frau Ritter,\par +nachfolgend erhalten Sie Ihr gewünschtes Angebot über ein(e) GCMSD.\\ +Es umfasst im Einzelnen: +\begin{itemize} +\item Automatischer Probengeber 7650A (\#1) +\item 5977C MSD-Paket mit 8860 GC (\#2) +\begin{itemize} +\item Konfiguration mit Turbopumpe (\#3) +\end{itemize} +\end{itemize} +Für Rückfragen und Änderungswünsche stehe ich Ihnen gerne zur Verfügung.\par +Mit freundlichen Grüßen\\ +\includegraphics[width = 5cm]{signWoitschetzki.png} +\vspace{1cm} \\ + +\begin{center} +\begin{longtable} +{| cp{0.595\textwidth} crr |} \hline +\textbf{\#} & \textbf{Produktbeschreibung} (Produktnummer) & \textbf{Menge} & \textbf{Discount} & \textbf{Preis}\\ \hline \endhead +1 &\textbf{Automatischer Probengeber 7650A} (G4567A)\newline Automatischer Flüssigprobengeber mit 50 Probenplätzen.\newline Listenpreis: \SI{16952}{\sieuro}&1&\SI{25}{\%}&\SI{12714}{\sieuro}\\ +2 &\textbf{5977C MSD-Paket mit 8860 GC} (G7082CW)\newline 8860 GC mit S/SL-Inlet und MSD-Interface, 5977C MSD mit Edelstahl-Quelle, Masshunter-Workstation inkl. PC\newline Listenpreis: \SI{83099}{\sieuro}&1&\SI{25}{\%}&\SI{62324.25}{\sieuro}\\ +3 &\textbf{Konfiguration mit Turbopumpe} (G7082CW\#002)\newline \newline Listenpreis: \SI{11884}{\sieuro}&1&\SI{25}{\%}&\SI{8913}{\sieuro}\\ +\hline +\end{longtable} +\end{center} + +\vspace{-2cm} +\begin{flushright} + +\begin{tabular}{|rr|} +\hline +\textbf{Summe netto} & \SI{83951.25}{\sieuro}\\ +\textbf{Versand und Bereitstellungskosten (3\%)} & \SI{2518.5375}{\sieuro}\\ +\textbf{Gesamtsumme netto} & \SI{86469.7875}{\sieuro}\\ +\hline +\end{tabular} + +\end{flushright} + +Der Betrag versteht sich zzgl. der gesetzlichen Steuern.\\ +Diese werden im Rechnungszeitraum auf der Rechnung gesondert ausgewiesen.\\ +Zahlungsbedingungen: 30 Tage netto ab Rechnungsdatum.\\ +Incoterm (2010) für Lieferungen innerhalb Deutschlands: DDP. +\begin{small} + +\textbf{Gewährleistung:}\\ +Die Gewährleistung für Zubehör und Ersatzteilprodukte und für Analytik-Hardwareprodukte beträgt 12 Monate. + +\textbf{Hinweis:}\\ +Für den Verkauf der in diesem Angebot aufgeführten Standard-Produkte und -Services gelten die aktuellen \emph{Agilent Geschäftsbedingungen} und alle sonstigen anwendbaren Zusatzbedingungen sowie zusätzliche Bedingungen, soweit darauf hier Bezug genommen wird. Soweit Produkte oder Services nach speziellen Kundenanforderungen hergestellt, konfiguriert oder angepasst werden, gelten für den Verkauf aller in diesem Angebot aufgeführten Produkte und Services die aktuellen \emph{Agilent Geschäftsbedingungen für kundenspezifische Produkte} und alle sonstigen anwendbaren Zusatzbedingungen sowie zusätzliche Bedingungen, soweit darauf hier Bezug genommen wird. Eine Kopie der maßgeblichen Bedingungen ist entweder beigefügt oder wurde Ihnen bereits zur Verfügung gestellt. Sollten Sie keine Kopie erhalten haben oder eine weitere Kopie benötigen, setzen Sie sich bitte mit uns in Verbindung. Soweit Sie mit Agilent eine gesonderte Vereinbarung getroffen haben, die den Verkauf der in diesem Angebot aufgeführten Produkte und Services umfasst, sind die Bestimmungen dieser Vereinbarung anwendbar. Abweichende oder ergänzende Vereinbarungen, insbesondere widersprechende Geschäftsbedingungen, sind nur gültig, wenn sie ausdrücklich schriftlich vereinbart worden sind. Die angegebenen Daten zur Verfügbarkeit von Produkten und Services sind vorläufig. Die tatsächlichen Lieferzeiten bzw. Lieferperioden werden Ihnen bei Auftragsbestätigung mitgeteilt. Waren, Technologien oder Software, die aus den Vereinigten Staaten von Amerika (\emph{USA}) oder anderen exportierenden Ländern ausgeführt werden, unterliegen den Ausfuhrbestimmungen der USA sowie anderer Rechtsordnungen. Bei Ausfuhr ist der Kunde dafür verantwortlich, dass die anwendbaren Ausfuhrbestimmungen eingehalten werden. +\end{small} + +\begin{scriptsize} +Agilent Technologies Deutschland GmbH, Hewlett-Packard-Str. 8, D-76337 Waldbronn\\ +Telefon +49 (0)7243-602-0\\ +USt.-IdNr.: DE812729296, WEEE-Reg.-Nr. DE 86631749\\ +Sitz der Gesellschaft: Waldbronn – Amtsgericht Mannheim, HRB 723782\\ +Geschäftsführer: Dr. Andreas Kistner (Vorsitzender der Geschäftsführung), Armin Jehle, Norbert Sabatzki, Dr. Knut Wintergerst\\ +\href{www.agilent.com}{www.agilent.com} +\end{scriptsize} +\end{document} + diff --git a/Gremlin_BlazorServer/wwwroot/quotes/Grünenthal_GmbH/2023-8-Ritter-GCMSD/DE-83PE89-823-269.tsv b/Gremlin_BlazorServer/wwwroot/quotes/Grünenthal_GmbH/2023-8-Ritter-GCMSD/DE-83PE89-823-269.tsv new file mode 100644 index 0000000..c9f4d22 --- /dev/null +++ b/Gremlin_BlazorServer/wwwroot/quotes/Grünenthal_GmbH/2023-8-Ritter-GCMSD/DE-83PE89-823-269.tsv @@ -0,0 +1,4 @@ +# Part Number Opt PL Description Qty Price EUR Breaks EUR Uplift % Total Discount % Net EUR Total EUR Sales Discount YA9% Contractual Discount Y99% Promotion Discount Y07% Demo Discount Y04% PH Code PH Description YMax +1 G4567A AZ 7650 automatischer Fluessigprobengeber 1 16952 0 0 25 12714 12714 25 0 0 0 ISG100G140 Autosampler +2 G7082CW BZ 5977C MSD-Paket mit 8860 GC 1 83099 0 0 25 62324.25 62324.25 25 0 0 0 ISG310G310 GCMS SQ Bundle +3 G7082CW 002 BZ TURBOPUMPE 1 11884 0 0 25 8913 8913 25 0 0 0 diff --git a/Gremlin_BlazorServer/wwwroot/quotes/Grünenthal_GmbH/2023-8-Ritter-GCMSD/DE-83PE89-823-270.pdf b/Gremlin_BlazorServer/wwwroot/quotes/Grünenthal_GmbH/2023-8-Ritter-GCMSD/DE-83PE89-823-270.pdf new file mode 100644 index 0000000..6bafa5e Binary files /dev/null and b/Gremlin_BlazorServer/wwwroot/quotes/Grünenthal_GmbH/2023-8-Ritter-GCMSD/DE-83PE89-823-270.pdf differ diff --git a/Gremlin_BlazorServer/wwwroot/quotes/Grünenthal_GmbH/2023-8-Ritter-GCMSD/DE-83PE89-823-270.tex b/Gremlin_BlazorServer/wwwroot/quotes/Grünenthal_GmbH/2023-8-Ritter-GCMSD/DE-83PE89-823-270.tex new file mode 100644 index 0000000..e1f280e --- /dev/null +++ b/Gremlin_BlazorServer/wwwroot/quotes/Grünenthal_GmbH/2023-8-Ritter-GCMSD/DE-83PE89-823-270.tex @@ -0,0 +1,131 @@ +\documentclass[a4paper,ngerman,parskip,10pt]{scrlttr2} +\usepackage{lmodern} +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} +\usepackage{babel} +\usepackage[hidelinks]{hyperref} +\usepackage[left=2cm, right=2cm, top=2cm, bottom=2cm]{geometry} + +\usepackage[table]{xcolor} +\usepackage[right]{{eurosym}} +\usepackage[locale=DE]{{siunitx}} +\usepackage{{scrlayer-scrpage}} +\usepackage{{lastpage}} +\usepackage{{graphicx}} +\usepackage{{multirow}} +\usepackage{{longtable}} +\usepackage{{enumitem}} +\usepackage{{fp, xstring, spreadtab, numprint}} +\DeclareSIUnit{{\sieuro}}{{\mbox{{\euro}}}} +\rohead{DE-83PE89-823-270} +\cfoot{Seite \thepage/\pageref{LastPage}} +\sisetup{round-integer-to-decimal,round-precision=2,round-mode=places} +\newcommand{\produkttitel}[1]{\textsc{#1}} +\renewcommand{\arraystretch}{1.2} +\definecolor{AgilentBlau}{HTML}{0085d5} +\setlist{noitemsep} +\begin{document} +\begin{tabular}{p{0.4\hsize}p{0.5\hsize}} +\multirow{4}{*}{\includegraphics[width=0.9\hsize]{agilentLogo.png}} +&\normalsize{Agilent Technologies Deutschland GmbH}\\ +&\normalsize{Life Sciences \& Chemical Analysis}\\ +&\normalsize{Hewlett-Packard-Str. 8}\\ +&\normalsize{D-76337 Waldbronn} +\end{tabular} +\par +\begin{flushright} + +\colorbox{AgilentBlau}{\textcolor{white}{\textsc{\Huge{Angebot}}}} +\end{flushright} +\begin{tabular}{p{0.4\hsize}p{0.6\hsize}} + + & +\multirow{4}{*}{ +\begin{tabular}{|ll|} +\hline +\textbf{Angebotsnummer:}&DE-83PE89-823-270\\ +Angebotdatum:&\today\\ +Angebotsgültigkeit:&60 Tage\\\textbf{Ansprechpartner:}&Sascha Woitschetzki\\ +Telefon: &+49 208 74129134\\ +Mobil:&+49 163 9681131\\ +E-Mail:&\href{mailto:sascha.woitschetzki@non.agilent.com}{sascha.woitschetzki@non.agilent.com}\\ +\textbf{Auftragsannahme:}&\href{mailto:salesservices\_germany@agilent.com}{salesservices\_germany@agilent.com}\\ +\hline +\end{tabular} +}\\ +Frau Stefanie Ritter +\\ +Grünenthal GmbH +\\ +Zieglerstr. 6 +\\ +52224 Stolberg +\\ +&\\ +&\\ +\end{tabular} +\vspace{1cm}\par +Sehr geehrte Frau Ritter,\par +nachfolgend erhalten Sie Ihr gewünschtes Angebot über ein(e) GCMSD.\\ +Es umfasst im Einzelnen: +\begin{itemize} +\item Autosampler mit 16 Probenplätzen (\#1) +\item Autosamplererweiterung auf 150 Probenplätze (\#2) +\item 5977C MSD-Paket mit 8860 GC (\#3) +\begin{itemize} +\item Konfiguration mit Turbopumpe (\#4) +\end{itemize} +\end{itemize} +Für Rückfragen und Änderungswünsche stehe ich Ihnen gerne zur Verfügung.\par +Mit freundlichen Grüßen\\ +\includegraphics[width = 5cm]{signWoitschetzki.png} +\vspace{1cm} \\ + +\begin{center} +\begin{longtable} +{| cp{0.595\textwidth} crr |} \hline +\textbf{\#} & \textbf{Produktbeschreibung} (Produktnummer) & \textbf{Menge} & \textbf{Discount} & \textbf{Preis}\\ \hline \endhead +1 &\textbf{Automatischer Probengeber 7693A} (G4513A)\newline Zur Injektion flüssiger Proben, 16 Probenplätze, Befestigungsstift, Parkhalterung für den GC, 10 µl-Spritze und Lösemittelflaschen.\newline Listenpreis: \SI{9476}{\sieuro}&1&\SI{25}{\%}&\SI{7107}{\sieuro}\\ +2 &\textbf{Autosampler-Erweiterung auf 150 Probenplätze} (G4514A)\newline Erweiterung für den 7693A Autosampler, 150 Probenplätze auf drei herausnehmbaren Probenträgern. Optional mit kühl-/heizbaren Probenträgern, Barcodeleser, Probenvorbereitungsplätze (Heizen, Mischen) und Sample Prep Software.\newline Listenpreis: \SI{11092}{\sieuro}&1&\SI{25}{\%}&\SI{8319}{\sieuro}\\ +3 &\textbf{5977C MSD-Paket mit 8860 GC} (G7082CW)\newline 8860 GC mit S/SL-Inlet und MSD-Interface, 5977C MSD mit Edelstahl-Quelle, Masshunter-Workstation inkl. PC\newline Listenpreis: \SI{83099}{\sieuro}&1&\SI{25}{\%}&\SI{62324.25}{\sieuro}\\ +4 &\textbf{Konfiguration mit Turbopumpe} (G7082CW\#002)\newline \newline Listenpreis: \SI{11884}{\sieuro}&1&\SI{25}{\%}&\SI{8913}{\sieuro}\\ +\hline +\end{longtable} +\end{center} + +\vspace{-2cm} +\begin{flushright} + +\begin{tabular}{|rr|} +\hline +\textbf{Summe netto} & \SI{86663.25}{\sieuro}\\ +\textbf{Versand und Bereitstellungskosten (3\%)} & \SI{2599.8975}{\sieuro}\\ +\textbf{Gesamtsumme netto} & \SI{89263.1475}{\sieuro}\\ +\hline +\end{tabular} + +\end{flushright} + +Der Betrag versteht sich zzgl. der gesetzlichen Steuern.\\ +Diese werden im Rechnungszeitraum auf der Rechnung gesondert ausgewiesen.\\ +Zahlungsbedingungen: 30 Tage netto ab Rechnungsdatum.\\ +Incoterm (2010) für Lieferungen innerhalb Deutschlands: DDP. +\begin{small} + +\textbf{Gewährleistung:}\\ +Die Gewährleistung für Zubehör und Ersatzteilprodukte und für Analytik-Hardwareprodukte beträgt 12 Monate. + +\textbf{Hinweis:}\\ +Für den Verkauf der in diesem Angebot aufgeführten Standard-Produkte und -Services gelten die aktuellen \emph{Agilent Geschäftsbedingungen} und alle sonstigen anwendbaren Zusatzbedingungen sowie zusätzliche Bedingungen, soweit darauf hier Bezug genommen wird. Soweit Produkte oder Services nach speziellen Kundenanforderungen hergestellt, konfiguriert oder angepasst werden, gelten für den Verkauf aller in diesem Angebot aufgeführten Produkte und Services die aktuellen \emph{Agilent Geschäftsbedingungen für kundenspezifische Produkte} und alle sonstigen anwendbaren Zusatzbedingungen sowie zusätzliche Bedingungen, soweit darauf hier Bezug genommen wird. Eine Kopie der maßgeblichen Bedingungen ist entweder beigefügt oder wurde Ihnen bereits zur Verfügung gestellt. Sollten Sie keine Kopie erhalten haben oder eine weitere Kopie benötigen, setzen Sie sich bitte mit uns in Verbindung. Soweit Sie mit Agilent eine gesonderte Vereinbarung getroffen haben, die den Verkauf der in diesem Angebot aufgeführten Produkte und Services umfasst, sind die Bestimmungen dieser Vereinbarung anwendbar. Abweichende oder ergänzende Vereinbarungen, insbesondere widersprechende Geschäftsbedingungen, sind nur gültig, wenn sie ausdrücklich schriftlich vereinbart worden sind. Die angegebenen Daten zur Verfügbarkeit von Produkten und Services sind vorläufig. Die tatsächlichen Lieferzeiten bzw. Lieferperioden werden Ihnen bei Auftragsbestätigung mitgeteilt. Waren, Technologien oder Software, die aus den Vereinigten Staaten von Amerika (\emph{USA}) oder anderen exportierenden Ländern ausgeführt werden, unterliegen den Ausfuhrbestimmungen der USA sowie anderer Rechtsordnungen. Bei Ausfuhr ist der Kunde dafür verantwortlich, dass die anwendbaren Ausfuhrbestimmungen eingehalten werden. +\end{small} + +\begin{scriptsize} +Agilent Technologies Deutschland GmbH, Hewlett-Packard-Str. 8, D-76337 Waldbronn\\ +Telefon +49 (0)7243-602-0\\ +USt.-IdNr.: DE812729296, WEEE-Reg.-Nr. DE 86631749\\ +Sitz der Gesellschaft: Waldbronn – Amtsgericht Mannheim, HRB 723782\\ +Geschäftsführer: Dr. Andreas Kistner (Vorsitzender der Geschäftsführung), Armin Jehle, Norbert Sabatzki, Dr. Knut Wintergerst\\ +\href{www.agilent.com}{www.agilent.com} +\end{scriptsize} +\end{document} + diff --git a/Gremlin_BlazorServer/wwwroot/quotes/Grünenthal_GmbH/2023-8-Ritter-GCMSD/DE-83PE89-823-270.tsv b/Gremlin_BlazorServer/wwwroot/quotes/Grünenthal_GmbH/2023-8-Ritter-GCMSD/DE-83PE89-823-270.tsv new file mode 100644 index 0000000..65b04df --- /dev/null +++ b/Gremlin_BlazorServer/wwwroot/quotes/Grünenthal_GmbH/2023-8-Ritter-GCMSD/DE-83PE89-823-270.tsv @@ -0,0 +1,5 @@ +# Part Number Opt PL Description Qty Price EUR Breaks EUR Uplift % Total Discount % Net EUR Total EUR Sales Discount YA9% Contractual Discount Y99% Promotion Discount Y07% Demo Discount Y04% PH Code PH Description YMax +1 G4513A AZ 7693A automatischer Probengeber 1 9476 0 0 25 7107 7107 25 0 0 0 ISG100G141 Autosampler +2 G4514A AZ 7693A Probenteller, 150 Probenflaschen 1 11092 0 0 25 8319 8319 25 0 0 0 ISG100G141 Autosampler +3 G7082CW BZ 5977C MSD-Paket mit 8860 GC 1 83099 0 0 25 62324.25 62324.25 25 0 0 0 ISG310G310 GCMS SQ Bundle +4 G7082CW 002 BZ TURBOPUMPE 1 11884 0 0 25 8913 8913 25 0 0 0 diff --git a/Gremlin_BlazorServer/wwwroot/quotes/HyperChrom_Deutschland_GmbH/2023-8-Boeker-7000D/DE-83PE89-823-268.pdf b/Gremlin_BlazorServer/wwwroot/quotes/HyperChrom_Deutschland_GmbH/2023-8-Boeker-7000D/DE-83PE89-823-268.pdf new file mode 100644 index 0000000..8125637 Binary files /dev/null and b/Gremlin_BlazorServer/wwwroot/quotes/HyperChrom_Deutschland_GmbH/2023-8-Boeker-7000D/DE-83PE89-823-268.pdf differ diff --git a/Gremlin_BlazorServer/wwwroot/quotes/HyperChrom_Deutschland_GmbH/2023-8-Boeker-7000D/DE-83PE89-823-268.tex b/Gremlin_BlazorServer/wwwroot/quotes/HyperChrom_Deutschland_GmbH/2023-8-Boeker-7000D/DE-83PE89-823-268.tex new file mode 100644 index 0000000..904db07 --- /dev/null +++ b/Gremlin_BlazorServer/wwwroot/quotes/HyperChrom_Deutschland_GmbH/2023-8-Boeker-7000D/DE-83PE89-823-268.tex @@ -0,0 +1,130 @@ +\documentclass[a4paper,ngerman,parskip,10pt]{scrlttr2} +\usepackage{lmodern} +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} +\usepackage{babel} +\usepackage[hidelinks]{hyperref} +\usepackage[left=2cm, right=2cm, top=2cm, bottom=2cm]{geometry} + +\usepackage[table]{xcolor} +\usepackage[right]{{eurosym}} +\usepackage[locale=DE]{{siunitx}} +\usepackage{{scrlayer-scrpage}} +\usepackage{{lastpage}} +\usepackage{{graphicx}} +\usepackage{{multirow}} +\usepackage{{longtable}} +\usepackage{{enumitem}} +\usepackage{{fp, xstring, spreadtab, numprint}} +\DeclareSIUnit{{\sieuro}}{{\mbox{{\euro}}}} +\rohead{DE-83PE89-823-268} +\cfoot{Seite \thepage/\pageref{LastPage}} +\sisetup{round-integer-to-decimal,round-precision=2,round-mode=places} +\newcommand{\produkttitel}[1]{\textsc{#1}} +\renewcommand{\arraystretch}{1.2} +\definecolor{AgilentBlau}{HTML}{0085d5} +\setlist{noitemsep} +\begin{document} +\begin{tabular}{p{0.4\hsize}p{0.5\hsize}} +\multirow{4}{*}{\includegraphics[width=0.9\hsize]{agilentLogo.png}} +&\normalsize{Agilent Technologies Deutschland GmbH}\\ +&\normalsize{Life Sciences \& Chemical Analysis}\\ +&\normalsize{Hewlett-Packard-Str. 8}\\ +&\normalsize{D-76337 Waldbronn} +\end{tabular} +\par +\begin{flushright} + +\colorbox{AgilentBlau}{\textcolor{white}{\textsc{\Huge{Angebot}}}} +\end{flushright} +\begin{tabular}{p{0.4\hsize}p{0.6\hsize}} + + & +\multirow{4}{*}{ +\begin{tabular}{|ll|} +\hline +\textbf{Angebotsnummer:}&DE-83PE89-823-268\\ +Angebotdatum:&\today\\ +Angebotsgültigkeit:&60 Tage\\\textbf{Ansprechpartner:}&Sascha Woitschetzki\\ +Telefon: &+49 208 74129134\\ +Mobil:&+49 163 9681131\\ +E-Mail:&\href{mailto:sascha.woitschetzki@non.agilent.com}{sascha.woitschetzki@non.agilent.com}\\ +\textbf{Auftragsannahme:}&\href{mailto:salesservices\_germany@agilent.com}{salesservices\_germany@agilent.com}\\ +\hline +\end{tabular} +}\\ +Herr Peter Boeker +\\ +HyperChrom Deutschland GmbH +\\ +Endenicher Allee 11-13 +\\ +53115 Bonn +\\ +&\\ +&\\ +\end{tabular} +\vspace{1cm}\par +Sehr geehrter Herr Boeker,\par +nachfolgend erhalten Sie Ihr gewünschtes Angebot über ein(e) 7000D.\\ +Es umfasst im Einzelnen: +\begin{itemize} +\item 7000D refurbished (\#1) +\begin{itemize} +\item Konfiguration für 8890 GC (\#2) +\end{itemize} +\end{itemize} +Für Rückfragen und Änderungswünsche stehe ich Ihnen gerne zur Verfügung.\par +Mit freundlichen Grüßen\\ +\includegraphics[width = 5cm]{signWoitschetzki.png} +\vspace{1cm} \\ + +\textbf{Wichtiger Hinweis zur Bestellung von überholten Geräten}\\ +Bitte beachten Sie, dass in der Regel nur wenige gebrauchte Geräte auf Lager sind und diese ohne die Möglichkeit einer Reservierung auf „first come, first serve“-Basis verkauft werden. Um lange Lieferzeiten zu vermeiden, sollte daher bei konkretem Interesse zunächst der Lagerstand überprüft werden. Die aktuellen Lagerbestände sind: + +\begin{center} +\begin{longtable} +{| cp{0.71\textwidth} cr |} \hline +\textbf{\#} & \textbf{Produktbeschreibung} (Produktnummer) & \textbf{Menge} & \textbf{Preis}\\ \hline \endhead +1 &\textbf{7000D refurbished} (G7010BAR)\newline Agilent zertifiziertes und gebrauchtes GC/QQQ 7000D mit EI-Quelle.&1&\SI{69890.7}{\sieuro}\\ +2 &\textbf{Konfiguration für 8890 GC} (G7010BAR\#245)\newline Anschlüsse passend für 8890 GC.&1&\SI{-745.2}{\sieuro}\\ +\hline +\end{longtable} +\end{center} + +\vspace{-2cm} +\begin{flushright} + +\begin{tabular}{|rr|} +\hline +\textbf{Summe netto} & \SI{69145.5}{\sieuro}\\ +\textbf{Versand und Bereitstellungskosten (3\%)} & \SI{2074.365}{\sieuro}\\ +\textbf{Gesamtsumme netto} & \SI{71219.865}{\sieuro}\\ +\hline +\end{tabular} + +\end{flushright} + +Der Betrag versteht sich zzgl. der gesetzlichen Steuern.\\ +Diese werden im Rechnungszeitraum auf der Rechnung gesondert ausgewiesen.\\ +Zahlungsbedingungen: 30 Tage netto ab Rechnungsdatum.\\ +Incoterm (2010) für Lieferungen innerhalb Deutschlands: DDP. +\begin{small} + +\textbf{Gewährleistung:}\\ +Die Gewährleistung für Zubehör und Ersatzteilprodukte und für Analytik-Hardwareprodukte beträgt 12 Monate. + +\textbf{Hinweis:}\\ +Für den Verkauf der in diesem Angebot aufgeführten Standard-Produkte und -Services gelten die aktuellen \emph{Agilent Geschäftsbedingungen} und alle sonstigen anwendbaren Zusatzbedingungen sowie zusätzliche Bedingungen, soweit darauf hier Bezug genommen wird. Soweit Produkte oder Services nach speziellen Kundenanforderungen hergestellt, konfiguriert oder angepasst werden, gelten für den Verkauf aller in diesem Angebot aufgeführten Produkte und Services die aktuellen \emph{Agilent Geschäftsbedingungen für kundenspezifische Produkte} und alle sonstigen anwendbaren Zusatzbedingungen sowie zusätzliche Bedingungen, soweit darauf hier Bezug genommen wird. Eine Kopie der maßgeblichen Bedingungen ist entweder beigefügt oder wurde Ihnen bereits zur Verfügung gestellt. Sollten Sie keine Kopie erhalten haben oder eine weitere Kopie benötigen, setzen Sie sich bitte mit uns in Verbindung. Soweit Sie mit Agilent eine gesonderte Vereinbarung getroffen haben, die den Verkauf der in diesem Angebot aufgeführten Produkte und Services umfasst, sind die Bestimmungen dieser Vereinbarung anwendbar. Abweichende oder ergänzende Vereinbarungen, insbesondere widersprechende Geschäftsbedingungen, sind nur gültig, wenn sie ausdrücklich schriftlich vereinbart worden sind. Die angegebenen Daten zur Verfügbarkeit von Produkten und Services sind vorläufig. Die tatsächlichen Lieferzeiten bzw. Lieferperioden werden Ihnen bei Auftragsbestätigung mitgeteilt. Waren, Technologien oder Software, die aus den Vereinigten Staaten von Amerika (\emph{USA}) oder anderen exportierenden Ländern ausgeführt werden, unterliegen den Ausfuhrbestimmungen der USA sowie anderer Rechtsordnungen. Bei Ausfuhr ist der Kunde dafür verantwortlich, dass die anwendbaren Ausfuhrbestimmungen eingehalten werden. +\end{small} + +\begin{scriptsize} +Agilent Technologies Deutschland GmbH, Hewlett-Packard-Str. 8, D-76337 Waldbronn\\ +Telefon +49 (0)7243-602-0\\ +USt.-IdNr.: DE812729296, WEEE-Reg.-Nr. DE 86631749\\ +Sitz der Gesellschaft: Waldbronn – Amtsgericht Mannheim, HRB 723782\\ +Geschäftsführer: Dr. Andreas Kistner (Vorsitzender der Geschäftsführung), Armin Jehle, Norbert Sabatzki, Dr. Knut Wintergerst\\ +\href{www.agilent.com}{www.agilent.com} +\end{scriptsize} +\end{document} + diff --git a/Gremlin_BlazorServer/wwwroot/quotes/HyperChrom_Deutschland_GmbH/2023-8-Boeker-7000D/DE-83PE89-823-268.tsv b/Gremlin_BlazorServer/wwwroot/quotes/HyperChrom_Deutschland_GmbH/2023-8-Boeker-7000D/DE-83PE89-823-268.tsv new file mode 100644 index 0000000..a95fc6c --- /dev/null +++ b/Gremlin_BlazorServer/wwwroot/quotes/HyperChrom_Deutschland_GmbH/2023-8-Boeker-7000D/DE-83PE89-823-268.tsv @@ -0,0 +1,3 @@ +# Part Number Opt PL Description Qty Price EUR Breaks EUR Uplift % Total Discount % Net EUR Total EUR Sales Discount YA9% Contractual Discount Y99% Promotion Discount Y07% Demo Discount Y04% PH Code PH Description YMax +1 G7010BAR RB Agilent zert. gebr. 7000D MS/MS 1 232969 0 0 70 69890.7 69890.7 70 0 0 0 ISRG40RB10 Remarketed GC/MS/MS +2 G7010BAR 245 RB MS fuer 8890 GC 1 -2484 0 0 70 -745.2 -745.2 70 0 0 0 diff --git a/Gremlin_BlazorServer/wwwroot/quotes/SenseUp_GmbH/2023-8-Potzkei-GC/DE-83PE89-823-269.pdf b/Gremlin_BlazorServer/wwwroot/quotes/SenseUp_GmbH/2023-8-Potzkei-GC/DE-83PE89-823-269.pdf new file mode 100644 index 0000000..ad33e28 Binary files /dev/null and b/Gremlin_BlazorServer/wwwroot/quotes/SenseUp_GmbH/2023-8-Potzkei-GC/DE-83PE89-823-269.pdf differ diff --git a/Gremlin_BlazorServer/wwwroot/quotes/SenseUp_GmbH/2023-8-Potzkei-GC/DE-83PE89-823-269.tex b/Gremlin_BlazorServer/wwwroot/quotes/SenseUp_GmbH/2023-8-Potzkei-GC/DE-83PE89-823-269.tex new file mode 100644 index 0000000..8d1bd19 --- /dev/null +++ b/Gremlin_BlazorServer/wwwroot/quotes/SenseUp_GmbH/2023-8-Potzkei-GC/DE-83PE89-823-269.tex @@ -0,0 +1,147 @@ +\documentclass[a4paper,ngerman,parskip,10pt]{scrlttr2} +\usepackage{lmodern} +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} +\usepackage{babel} +\usepackage[hidelinks]{hyperref} +\usepackage[left=2cm, right=2cm, top=2cm, bottom=2cm]{geometry} + +\usepackage[table]{xcolor} +\usepackage[right]{{eurosym}} +\usepackage[locale=DE]{{siunitx}} +\usepackage{{scrlayer-scrpage}} +\usepackage{{lastpage}} +\usepackage{{graphicx}} +\usepackage{{multirow}} +\usepackage{{longtable}} +\usepackage{{enumitem}} +\usepackage{{fp, xstring, spreadtab, numprint}} +\DeclareSIUnit{{\sieuro}}{{\mbox{{\euro}}}} +\rohead{DE-83PE89-823-269} +\cfoot{Seite \thepage/\pageref{LastPage}} +\sisetup{round-integer-to-decimal,round-precision=2,round-mode=places} +\newcommand{\produkttitel}[1]{\textsc{#1}} +\renewcommand{\arraystretch}{1.2} +\definecolor{AgilentBlau}{HTML}{0085d5} +\setlist{noitemsep} +\begin{document} +\begin{tabular}{p{0.4\hsize}p{0.5\hsize}} +\multirow{4}{*}{\includegraphics[width=0.9\hsize]{agilentLogo.png}} +&\normalsize{Agilent Technologies Deutschland GmbH}\\ +&\normalsize{Life Sciences \& Chemical Analysis}\\ +&\normalsize{Hewlett-Packard-Str. 8}\\ +&\normalsize{D-76337 Waldbronn} +\end{tabular} +\par +\begin{flushright} + +\colorbox{AgilentBlau}{\textcolor{white}{\textsc{\Huge{Angebot}}}} +\end{flushright} +\begin{tabular}{p{0.4\hsize}p{0.6\hsize}} + + & +\multirow{4}{*}{ +\begin{tabular}{|ll|} +\hline +\textbf{Angebotsnummer:}&DE-83PE89-823-269\\ +Angebotdatum:&\today\\ +Angebotsgültigkeit:&60 Tage\\\textbf{Ansprechpartner:}&Sascha Woitschetzki\\ +Telefon: &+49 208 74129134\\ +Mobil:&+49 163 9681131\\ +E-Mail:&\href{mailto:sascha.woitschetzki@non.agilent.com}{sascha.woitschetzki@non.agilent.com}\\ +\textbf{Auftragsannahme:}&\href{mailto:salesservices\_germany@agilent.com}{salesservices\_germany@agilent.com}\\ +\hline +\end{tabular} +}\\ +Herr Janko Potzkei +\\ +SenseUp GmbH +\\ +Wilhelm-Johnen-Str. +\\ +52428 Jülich +\\ +&\\ +&\\ +\end{tabular} +\vspace{1cm}\par +Sehr geehrter Herr Potzkei,\par +nachfolgend erhalten Sie Ihr gewünschtes Angebot über ein(e) GC.\\ +Es umfasst im Einzelnen: +\begin{itemize} +\item 8890 Gaschromatograph (\#1) +\begin{itemize} +\item S/SL-Einlass (\#2) +\item Anschluss für MSD (\#3) +\item Flammenionisationsdetektor (\#4) +\end{itemize} +\item Automatischer Probengeber 7650A (\#5) +\item OpenLAB CDS 2 Workstation mit Software und Lizenzen, PC, Softwarewartungsvertrag: alle Updates und Upgrades, bevorzugter telefonischer Support. Laufzeit: 1 Jahr (\#6) +\begin{itemize} +\item Inkludierte Gerätelizenz (\#7) +\end{itemize} +\item DB-5 30m, 0,25 mm, 0,25 um (\#8) +\item 8890 GC (\#9) +\begin{itemize} +\item Wartungsvertrag (Laufzeit: 1 Jahr) (\#10) +\end{itemize} +\end{itemize} +Für Rückfragen und Änderungswünsche stehe ich Ihnen gerne zur Verfügung.\par +Mit freundlichen Grüßen\\ +\includegraphics[width = 5cm]{signWoitschetzki.png} +\vspace{1cm} \\ + +\begin{center} +\begin{longtable} +{| cp{0.71\textwidth} cr |} \hline +\textbf{\#} & \textbf{Produktbeschreibung} (Produktnummer) & \textbf{Menge} & \textbf{Preis}\\ \hline \endhead +1 &\textbf{8890 Gaschromatograph} (G3540A)\newline Agilent 8890 GC\newline Ofen bis 450 °C, Kühlen von 450 auf 50 °C in unter 4 Min., bis zu 2 Inlets und 4 Detektoren. Elektronische Druck- und Flusskontrolle (EPC; 0-99 psi, 0.001 psi Genauigkeit), retention time locking (RTL).&1&\SI{9928.45}{\sieuro}\\ +2 &\textbf{S/SL-Einlass} (G3540A\#112)\newline Split/Splitless-Einlasssystem für Kapillarsäulen mit elektronischer Drucksteuerung (EPC), max. 100 psi.&1&\SI{2521.07}{\sieuro}\\ +3 &\textbf{Anschluss für MSD} (G3540A\#201)\newline Linksseitig, Frontposition.&1&\SI{1222.31}{\sieuro}\\ +4 &\textbf{Flammenionisationsdetektor} (G3540A\#211)\newline Flammenionisationsdetektor mit elektronischer Fluss- /Drucksteuerung zur digitalen Steuerung aller Detektorgase. Optimiert für Kapillarsäulen.&1&\SI{2511.27}{\sieuro}\\ +5 &\textbf{Automatischer Probengeber 7650A} (G4567A)\newline Automatischer Flüssigprobengeber mit 50 Probenplätzen.&1&\SI{8308.18}{\sieuro}\\ +6 &\textbf{OpenLab CDS 2 Workstation Bundle} (M8414AA)\newline OpenLab CDS Workstation-Software, dateibasiert, \newline inklusive 2 Geräteverbindungslizenzen, 1 Jahr Software-Wartungsvertrag sowie telefonischem Support und Workstation-PC.&1&\SI{8673.3}{\sieuro}\\ +7 &\textbf{Inkludierte Gerätelizenz} (M8414AA\#002)\newline Für ein Agilent GC-System.&1&\SI{0}{\sieuro}\\ +8 &\textbf{DB-5 30m, 0,25 mm, 0,25 um} (122-5032)\newline &1&\SI{333.76}{\sieuro}\\ +9 &\textbf{8890 GC} (SYS-GC-8890)\newline &1&\SI{0}{\sieuro}\\ +10 &\textbf{Wartungsvertrag (Laufzeit: 1 Jahr)} (SYS-GC-8890\#0L1)\newline 1 jährliche Wartung inklusive aller turnusmäßig zu wechselnden Ersatzteilen, inklusive Fahrt- und Arbeitszeitkosten.&1&\SI{1218.17}{\sieuro}\\ +\hline +\end{longtable} +\end{center} + +\vspace{-2cm} +\begin{flushright} + +\begin{tabular}{|rr|} +\hline +\textbf{Summe netto} & \SI{34716.51}{\sieuro}\\ +\textbf{Versand und Bereitstellungskosten (3\%)} & \SI{1041.4953}{\sieuro}\\ +\textbf{Gesamtsumme netto} & \SI{35758.0053}{\sieuro}\\ +\hline +\end{tabular} + +\end{flushright} + +Der Betrag versteht sich zzgl. der gesetzlichen Steuern.\\ +Diese werden im Rechnungszeitraum auf der Rechnung gesondert ausgewiesen.\\ +Zahlungsbedingungen: 30 Tage netto ab Rechnungsdatum.\\ +Incoterm (2010) für Lieferungen innerhalb Deutschlands: DDP. +\begin{small} + +\textbf{Gewährleistung:}\\ +Die Gewährleistung für Zubehör und Ersatzteilprodukte und für Analytik-Hardwareprodukte beträgt 12 Monate. + +\textbf{Hinweis:}\\ +Für den Verkauf der in diesem Angebot aufgeführten Standard-Produkte und -Services gelten die aktuellen \emph{Agilent Geschäftsbedingungen} und alle sonstigen anwendbaren Zusatzbedingungen sowie zusätzliche Bedingungen, soweit darauf hier Bezug genommen wird. Soweit Produkte oder Services nach speziellen Kundenanforderungen hergestellt, konfiguriert oder angepasst werden, gelten für den Verkauf aller in diesem Angebot aufgeführten Produkte und Services die aktuellen \emph{Agilent Geschäftsbedingungen für kundenspezifische Produkte} und alle sonstigen anwendbaren Zusatzbedingungen sowie zusätzliche Bedingungen, soweit darauf hier Bezug genommen wird. Eine Kopie der maßgeblichen Bedingungen ist entweder beigefügt oder wurde Ihnen bereits zur Verfügung gestellt. Sollten Sie keine Kopie erhalten haben oder eine weitere Kopie benötigen, setzen Sie sich bitte mit uns in Verbindung. Soweit Sie mit Agilent eine gesonderte Vereinbarung getroffen haben, die den Verkauf der in diesem Angebot aufgeführten Produkte und Services umfasst, sind die Bestimmungen dieser Vereinbarung anwendbar. Abweichende oder ergänzende Vereinbarungen, insbesondere widersprechende Geschäftsbedingungen, sind nur gültig, wenn sie ausdrücklich schriftlich vereinbart worden sind. Die angegebenen Daten zur Verfügbarkeit von Produkten und Services sind vorläufig. Die tatsächlichen Lieferzeiten bzw. Lieferperioden werden Ihnen bei Auftragsbestätigung mitgeteilt. Waren, Technologien oder Software, die aus den Vereinigten Staaten von Amerika (\emph{USA}) oder anderen exportierenden Ländern ausgeführt werden, unterliegen den Ausfuhrbestimmungen der USA sowie anderer Rechtsordnungen. Bei Ausfuhr ist der Kunde dafür verantwortlich, dass die anwendbaren Ausfuhrbestimmungen eingehalten werden. +\end{small} + +\begin{scriptsize} +Agilent Technologies Deutschland GmbH, Hewlett-Packard-Str. 8, D-76337 Waldbronn\\ +Telefon +49 (0)7243-602-0\\ +USt.-IdNr.: DE812729296, WEEE-Reg.-Nr. DE 86631749\\ +Sitz der Gesellschaft: Waldbronn – Amtsgericht Mannheim, HRB 723782\\ +Geschäftsführer: Dr. Andreas Kistner (Vorsitzender der Geschäftsführung), Armin Jehle, Norbert Sabatzki, Dr. Knut Wintergerst\\ +\href{www.agilent.com}{www.agilent.com} +\end{scriptsize} +\end{document} + diff --git a/Gremlin_BlazorServer/wwwroot/quotes/SenseUp_GmbH/2023-8-Potzkei-GC/DE-83PE89-823-269.tsv b/Gremlin_BlazorServer/wwwroot/quotes/SenseUp_GmbH/2023-8-Potzkei-GC/DE-83PE89-823-269.tsv new file mode 100644 index 0000000..4fd93f6 --- /dev/null +++ b/Gremlin_BlazorServer/wwwroot/quotes/SenseUp_GmbH/2023-8-Potzkei-GC/DE-83PE89-823-269.tsv @@ -0,0 +1,11 @@ +# Part Number Opt PL Description Qty Price EUR Breaks EUR Uplift % Total Discount % Net EUR Total EUR Sales Discount YA9% Contractual Discount Y99% Promotion Discount Y07% Demo Discount Y04% PH Code PH Description YMax +1 G3540A AZ Agilent 8890 GC-System Kundenspezifisch 1 20258 0 0 50.99 9928.45 9928.45 50.99 0 0 0 ISG100G111 6890 GC system +2 G3540A 112 AZ 8890 100 psi Split/Splitless-Einlasszub. 1 5144 0 0 50.99 2521.07 2521.07 50.99 0 0 0 +3 G3540A 201 AZ MSD-Interface 1 2494 0 0 50.99 1222.31 1222.31 50.99 0 0 0 +4 G3540A 211 AZ 8890 FID Zubeh. optimiert f. Kapillare 1 5124 0 0 50.99 2511.27 2511.27 50.99 0 0 0 +5 G4567A AZ 7650 automatischer Fluessigprobengeber 1 16952 0 0 50.99 8308.18 8308.18 50.99 0 0 0 ISG100G140 Autosampler +6 M8414AA LI OpenLab CDS Workstation PC-Paket 1 17697 0 0 50.99 8673.3 8673.3 50.99 0 0 0 ISF300F110 OpenLAB CDS w/Hardware +7 M8414AA 002 LI GC Geraeteverbindung 1 0 0 0 50.99 0 0 50.99 0 0 0 +8 122-5032 JW DB-5 30m, 0,25 mm, 0,25 um 1 681 0 0 50.99 333.76 333.76 50.99 0 0 0 CSCG10C10B CapCol 5-type +9 SYS-GC-8890 74 8890 GC-System 1 0 0 0 29.99 0 0 29.99 0 0 0 TSSYS0SYGC Service Systems - Gas Chromatography > 29 +10 SYS-GC-8890 0L1 74 CrossLab Vorb. Wartung - 1J, kompl. 1 1740 0 0 29.99 1218.17 1218.17 29.99 0 0 0 TSSYS1 Serviced As Systems - 1 YR > 29