refactor of DB structure from LineItem -> Product -> CustomDescription relations

pull/1/head
DJh2o2 2023-04-11 15:59:36 +07:00
parent 8ab7f52b24
commit c71607a7b5
36 changed files with 2365 additions and 1785 deletions

@ -1200,7 +1200,7 @@ internal static class DbHelper
DescriptionText = fields[4],
CoverletterText = fields[5],
Notes = fields[6],
Product = new Product()
// Product = new Product()
// Supplier = new()
// {
// AccountName = fields[2] is "" or "RB" ? "Agilent Technologies" : fields[2]
@ -1267,19 +1267,19 @@ internal static class DbHelper
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);
}
// 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);

@ -4,10 +4,8 @@ using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Gremlin_BlazorServer.Data.DBClasses;
public class AccountConfiguration : IEntityTypeConfiguration<Account>
{
public void Configure(EntityTypeBuilder<Account> accountEntity)
{
public class AccountConfiguration : IEntityTypeConfiguration<Account> {
public void Configure(EntityTypeBuilder<Account> accountEntity) {
accountEntity.HasKey(e => e.AccountId);
accountEntity.HasMany(d => d.Contacts).WithOne(p => p.Account);
@ -45,10 +43,8 @@ public class AccountConfiguration : IEntityTypeConfiguration<Account>
}
}
public class ContactConfiguration : IEntityTypeConfiguration<Contact>
{
public void Configure(EntityTypeBuilder<Contact> contactEntity)
{
public class ContactConfiguration : IEntityTypeConfiguration<Contact> {
public void Configure(EntityTypeBuilder<Contact> contactEntity) {
contactEntity.HasKey(e => e.ContactId);
contactEntity.HasOne(p => p.Account).WithMany(d => d.Contacts).HasForeignKey(fk => fk.AccountId);
@ -81,14 +77,36 @@ public class ContactConfiguration : IEntityTypeConfiguration<Contact>
}
}
public class QuoteConfiguration : IEntityTypeConfiguration<Quote>
{
public void Configure(EntityTypeBuilder<Quote> quoteEntity)
{
public class SalesRepConfiguration : IEntityTypeConfiguration<SalesRep> {
public void Configure(EntityTypeBuilder<SalesRep> salesRepEntity) {
salesRepEntity.HasKey(e => e.SalesRepId);
salesRepEntity.HasOne(p => p.Account).WithMany(d => d.SalesReps).HasForeignKey(fk => fk.AccountId);
salesRepEntity.HasMany(q => q.ListOfQuotes).WithOne(c => c.SalesRep).HasForeignKey(fk => fk.SalesRepId);
salesRepEntity.Property(e => e.SalesRepId);
salesRepEntity.Property(e => e.AcademicTitle).HasDefaultValue("");
salesRepEntity.Property(e => e.FirstName).HasDefaultValue("");
salesRepEntity.Property(e => e.LastName).IsRequired();
salesRepEntity.Property(e => e.Gender).HasDefaultValue(0);
salesRepEntity.Property(e => e.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
salesRepEntity.Property(e => e.DataValidFrom).HasColumnType("DATETIME").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
salesRepEntity.Property(e => e.DataValidUntil).HasColumnType("DATETIME").HasDefaultValueSql("'9999-12-31 23:59:59.000000'").ValueGeneratedOnAdd();
salesRepEntity.Property(e => e.DataVersionNumber).HasDefaultValue(1).IsRequired();
salesRepEntity.Property(e => e.DataVersionComment).HasDefaultValue("");
salesRepEntity.Property(e => e.DataStatus).IsRequired();
salesRepEntity.Property(e => e.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken();
salesRepEntity.Property(e => e.DataModificationByUser).HasColumnType("TINYTEXT").IsRequired().HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
}
}
public class QuoteConfiguration : IEntityTypeConfiguration<Quote> {
public void Configure(EntityTypeBuilder<Quote> quoteEntity) {
quoteEntity.HasKey(e => e.QuoteId);
quoteEntity.HasOne(e => e.Recipient).WithMany(c => c.Quotes).HasForeignKey(fk => fk.RecipientId);
quoteEntity.HasOne(e => e.SalesRep).WithMany(c => c.SalesRepQuotes).HasForeignKey(fk => fk.SalesRepId);
quoteEntity.HasOne(e => e.SalesRep).WithMany(sR => sR.ListOfQuotes).HasForeignKey(fk => fk.SalesRepId);
quoteEntity.HasMany(d => d.LineItems).WithOne(p => p.Quote).HasForeignKey(fk => fk.QuoteId);
@ -116,14 +134,13 @@ public class QuoteConfiguration : IEntityTypeConfiguration<Quote>
}
}
public class LineItemConfiguration : IEntityTypeConfiguration<LineItem>
{
public void Configure(EntityTypeBuilder<LineItem> lineItemEntity)
{
public class LineItemConfiguration : IEntityTypeConfiguration<LineItem> {
public void Configure(EntityTypeBuilder<LineItem> lineItemEntity) {
lineItemEntity.HasKey(e => e.LineItemId);
lineItemEntity.HasOne(p => p.Quote).WithMany(d => d.LineItems).HasForeignKey(fk => fk.QuoteId);
lineItemEntity.HasOne(p => p.CustomDescription).WithMany(d => d.LineItems).HasForeignKey(fk => fk.CustomDescriptionId);
// lineItemEntity.HasOne(p => p.CustomDescription).WithMany(d => d.LineItems).HasForeignKey(fk => fk.CustomDescriptionId);
lineItemEntity.HasOne(lI => lI.Product).WithMany(p => p.LineItems).HasForeignKey(fK => fK.LineItemId);
lineItemEntity.Property(e => e.Position).IsRequired();
lineItemEntity.Property(e => e.Amount).IsRequired();
@ -153,39 +170,38 @@ public class LineItemConfiguration : IEntityTypeConfiguration<LineItem>
}
}
public class ProductConfiguration : IEntityTypeConfiguration<Product>
{
public void Configure(EntityTypeBuilder<Product> productEntity)
{
public class ProductConfiguration : IEntityTypeConfiguration<Product> {
public void Configure(EntityTypeBuilder<Product> productEntity) {
productEntity.HasKey(e => e.ProductId);
productEntity.HasOne(p => p.ProductLine).WithMany(d => d.Products).HasForeignKey(fk => fk.ProductLineCode).OnDelete(DeleteBehavior.Restrict);
productEntity.Property(e => e.ProductNumber).IsRequired();
productEntity.Property(e => e.OptionNumber).HasDefaultValue("");
productEntity.Property(e => e.SapShortDescription).HasDefaultValue("");
productEntity.Property(e => e.SapLongDescription).HasDefaultValue("");
productEntity.Property(e => e.Weight).HasDefaultValue(0);
productEntity.Property(e => e.ProductStatus).HasDefaultValue("Active");
productEntity.Property(e => e.IntroductionDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
productEntity.Property(e => e.ListPrice).IsRequired();
productEntity.Property(e => e.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
productEntity.Property(e => e.DataValidFrom).HasColumnType("DATETIME").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
productEntity.Property(e => e.DataValidUntil).HasColumnType("DATETIME").HasDefaultValueSql("'9999-12-31 23:59:59.000000'").ValueGeneratedOnAdd();
productEntity.Property(e => e.DataVersionNumber).HasDefaultValue(1).IsRequired();
productEntity.Property(e => e.DataVersionComment).HasDefaultValue("");
productEntity.Property(e => e.DataStatus).IsRequired().HasDefaultValue("Active");
productEntity.Property(e => e.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken();
productEntity.Property(e => e.DataModificationByUser).HasColumnType("TINYTEXT").IsRequired().HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
productEntity.HasOne(p => p.CustomDescription).WithOne(cD => cD.Product).HasForeignKey<CustomDescription>(cD => cD.ProductId);
productEntity.HasMany(p => p.LineItems).WithOne(lI => lI.Product).HasForeignKey(fK => fK.ProductId);
productEntity.Property(p => p.ProductNumber).IsRequired();
productEntity.Property(p => p.OptionNumber).HasDefaultValue("");
productEntity.Property(p => p.SapShortDescription).HasDefaultValue("");
productEntity.Property(p => p.SapLongDescription).HasDefaultValue("");
productEntity.Property(p => p.Weight).HasDefaultValue(0);
productEntity.Property(p => p.ProductStatus).HasDefaultValue("Active");
productEntity.Property(p => p.IntroductionDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
productEntity.Property(p => p.ListPrice).IsRequired();
productEntity.Property(p => p.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
productEntity.Property(p => p.DataValidFrom).HasColumnType("DATETIME").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
productEntity.Property(p => p.DataValidUntil).HasColumnType("DATETIME").HasDefaultValueSql("'9999-12-31 23:59:59.000000'").ValueGeneratedOnAdd();
productEntity.Property(p => p.DataVersionNumber).HasDefaultValue(1).IsRequired();
productEntity.Property(p => p.DataVersionComment).HasDefaultValue("");
productEntity.Property(p => p.DataStatus).IsRequired().HasDefaultValue("Active");
productEntity.Property(p => p.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken();
productEntity.Property(p => p.DataModificationByUser).HasColumnType("TINYTEXT").IsRequired().HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
}
}
public class CustomDescriptionConfiguration : IEntityTypeConfiguration<CustomDescription>
{
public void Configure(EntityTypeBuilder<CustomDescription> customDescriptionEntity)
{
customDescriptionEntity.HasKey(e => e.CustomDescriptionId);
customDescriptionEntity.HasOne(p => p.Product).WithOne(d => d.CustomDescription).IsRequired(false);
public class CustomDescriptionConfiguration : IEntityTypeConfiguration<CustomDescription> {
public void Configure(EntityTypeBuilder<CustomDescription> customDescriptionEntity) {
customDescriptionEntity.HasKey(cD => cD.CustomDescriptionId);
// customDescriptionEntity.HasOne(cD => cD.Product).WithOne(p => p.CustomDescription).HasForeignKey(fk => fk.ProductLineCode);
// customDescriptionEntity.HasOne(p => p.Supplier).WithMany(d => d.CustomDescriptions).IsRequired();
customDescriptionEntity.Property(e => e.ProductNumber).IsRequired();
@ -206,190 +222,83 @@ public class CustomDescriptionConfiguration : IEntityTypeConfiguration<CustomDes
}
}
public class ProductLineConfiguration : IEntityTypeConfiguration<ProductLine>
{
public void Configure(EntityTypeBuilder<ProductLine> productLineEntity)
{
productLineEntity
.HasMany(p => p.Products)
.WithOne(d => d.ProductLine)
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);
public class ProductLineConfiguration : IEntityTypeConfiguration<ProductLine> {
public void Configure(EntityTypeBuilder<ProductLine> productLineEntity) {
productLineEntity.HasMany(p => p.Products).WithOne(d => d.ProductLine).IsRequired().OnDelete(DeleteBehavior.Restrict);
productLineEntity.Property(e => e.ProductLineDescription).IsRequired();
productLineEntity
.Property(e => e.DataCreationDate)
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("CURRENT_TIMESTAMP")
.ValueGeneratedOnAdd();
productLineEntity
.Property(e => e.DataValidFrom)
.HasColumnType("DATETIME")
.HasDefaultValueSql("CURRENT_TIMESTAMP")
.ValueGeneratedOnAdd();
productLineEntity
.Property(e => e.DataValidUntil)
.HasColumnType("DATETIME")
.HasDefaultValueSql("'9999-12-31 23:59:59.000000'")
.ValueGeneratedOnAdd();
productLineEntity.Property(e => e.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
productLineEntity.Property(e => e.DataValidFrom).HasColumnType("DATETIME").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
productLineEntity.Property(e => e.DataValidUntil).HasColumnType("DATETIME").HasDefaultValueSql("'9999-12-31 23:59:59.000000'").ValueGeneratedOnAdd();
productLineEntity.Property(e => e.DataVersionNumber).HasDefaultValue(1).IsRequired();
productLineEntity.Property(e => e.DataVersionComment).HasDefaultValue("");
productLineEntity.Property(e => e.DataStatus).IsRequired().HasDefaultValue("Active");
productLineEntity
.Property(e => e.DataModificationDate)
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
.ValueGeneratedOnAddOrUpdate()
.IsConcurrencyToken();
productLineEntity
.Property(e => e.DataModificationByUser)
.HasColumnType("TINYTEXT")
.IsRequired()
.HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
productLineEntity.Property(e => e.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken();
productLineEntity.Property(e => e.DataModificationByUser).HasColumnType("TINYTEXT").IsRequired().HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
}
}
public class AccountTypeConfiguration : IEntityTypeConfiguration<AccountType>
{
public void Configure(EntityTypeBuilder<AccountType> accountTypeEntity)
{
public class AccountTypeConfiguration : IEntityTypeConfiguration<AccountType> {
public void Configure(EntityTypeBuilder<AccountType> accountTypeEntity) {
accountTypeEntity.HasKey(e => e.AccountTypeCode);
accountTypeEntity.HasMany(p => p.Accounts).WithOne(d => d.AccountType); //already defined in class Account
accountTypeEntity.Property(e => e.AccountTypeCode).IsRequired().HasColumnType("Char(3)");
accountTypeEntity
.Property(e => e.AccountTypeDescription)
.HasColumnType("Varchar(1000)")
.IsRequired();
accountTypeEntity
.Property(e => e.DataCreationDate)
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("CURRENT_TIMESTAMP")
.ValueGeneratedOnAdd();
accountTypeEntity
.Property(e => e.DataValidFrom)
.HasColumnType("DATETIME")
.HasDefaultValueSql("CURRENT_TIMESTAMP")
.ValueGeneratedOnAdd();
accountTypeEntity
.Property(e => e.DataValidUntil)
.HasColumnType("DATETIME")
.HasDefaultValueSql("'9999-12-31 23:59:59.000000'")
.ValueGeneratedOnAdd();
accountTypeEntity.Property(e => e.AccountTypeDescription).HasColumnType("Varchar(1000)").IsRequired();
accountTypeEntity.Property(e => e.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
accountTypeEntity.Property(e => e.DataValidFrom).HasColumnType("DATETIME").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
accountTypeEntity.Property(e => e.DataValidUntil).HasColumnType("DATETIME").HasDefaultValueSql("'9999-12-31 23:59:59.000000'").ValueGeneratedOnAdd();
accountTypeEntity.Property(e => e.DataVersionNumber).HasDefaultValue(1).IsRequired();
accountTypeEntity.Property(e => e.DataVersionComment).HasDefaultValue("");
accountTypeEntity.Property(e => e.DataStatus).IsRequired().HasDefaultValue("Active");
accountTypeEntity
.Property(e => e.DataModificationDate)
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
.ValueGeneratedOnAddOrUpdate()
.IsConcurrencyToken();
accountTypeEntity
.Property(e => e.DataModificationByUser)
.HasColumnType("TINYTEXT")
.IsRequired()
.HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
accountTypeEntity.Property(e => e.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken();
accountTypeEntity.Property(e => e.DataModificationByUser).HasColumnType("TINYTEXT").IsRequired().HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
}
}
public class SubMarketConfiguration : IEntityTypeConfiguration<SubMarket>
{
public void Configure(EntityTypeBuilder<SubMarket> subMarketEntity)
{
public class SubMarketConfiguration : IEntityTypeConfiguration<SubMarket> {
public void Configure(EntityTypeBuilder<SubMarket> subMarketEntity) {
subMarketEntity.HasKey(e => e.SubMarketCode);
subMarketEntity.HasMany(p => p.Accounts).WithOne(d => d.SubMarket); //already defined in class Account
subMarketEntity.Property(e => e.SubMarketCode).HasColumnType("Char(3)");
subMarketEntity
.Property(e => e.SubMarketDescription)
.HasColumnType("Varchar(1000)")
.IsRequired();
subMarketEntity
.Property(e => e.DataCreationDate)
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("CURRENT_TIMESTAMP")
.ValueGeneratedOnAdd();
subMarketEntity
.Property(e => e.DataValidFrom)
.HasColumnType("DATETIME")
.HasDefaultValueSql("CURRENT_TIMESTAMP")
.ValueGeneratedOnAdd();
subMarketEntity
.Property(e => e.DataValidUntil)
.HasColumnType("DATETIME")
.HasDefaultValueSql("'9999-12-31 23:59:59.000000'")
.ValueGeneratedOnAdd();
subMarketEntity.Property(e => e.SubMarketDescription).HasColumnType("Varchar(1000)").IsRequired();
subMarketEntity.Property(e => e.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
subMarketEntity.Property(e => e.DataValidFrom).HasColumnType("DATETIME").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
subMarketEntity.Property(e => e.DataValidUntil).HasColumnType("DATETIME").HasDefaultValueSql("'9999-12-31 23:59:59.000000'").ValueGeneratedOnAdd();
subMarketEntity.Property(e => e.DataVersionNumber).HasDefaultValue(1).IsRequired();
subMarketEntity.Property(e => e.DataVersionComment).HasDefaultValue("");
subMarketEntity.Property(e => e.DataStatus).IsRequired().HasDefaultValue("Active");
subMarketEntity
.Property(e => e.DataModificationDate)
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
.ValueGeneratedOnAddOrUpdate()
.IsConcurrencyToken();
subMarketEntity
.Property(e => e.DataModificationByUser)
.HasColumnType("TINYTEXT")
.IsRequired()
.HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
subMarketEntity.Property(e => e.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken();
subMarketEntity.Property(e => e.DataModificationByUser).HasColumnType("TINYTEXT").IsRequired().HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
}
}
public class RegisteredUserConfiguration : IEntityTypeConfiguration<RegisteredUser>
{
public void Configure(EntityTypeBuilder<RegisteredUser> registeredUserEntity)
{
public class RegisteredUserConfiguration : IEntityTypeConfiguration<RegisteredUser> {
public void Configure(EntityTypeBuilder<RegisteredUser> registeredUserEntity) {
registeredUserEntity.HasKey(e => e.RegisteredUserId);
registeredUserEntity.HasMany(d => d.RuSettings).WithOne(p => p.RegisteredUser).IsRequired();
registeredUserEntity.Property(e => e.UserName).IsRequired();
registeredUserEntity.Property(e => e.PasswordHash).IsRequired();
registeredUserEntity
.Property(e => e.DataCreationDate)
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("CURRENT_TIMESTAMP")
.ValueGeneratedOnAdd();
registeredUserEntity
.Property(e => e.DataModificationDate)
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
.ValueGeneratedOnAddOrUpdate()
.IsConcurrencyToken();
registeredUserEntity
.Property(e => e.DataModificationByUser)
.HasColumnType("TINYTEXT")
.HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
registeredUserEntity.Property(e => e.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
registeredUserEntity.Property(e => e.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken();
registeredUserEntity.Property(e => e.DataModificationByUser).HasColumnType("TINYTEXT").HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
}
}
public class RuSettingsConfiguration : IEntityTypeConfiguration<RuSettings>
{
public void Configure(EntityTypeBuilder<RuSettings> rUSettingsEntitity)
{
public class RuSettingsConfiguration : IEntityTypeConfiguration<RuSettings> {
public void Configure(EntityTypeBuilder<RuSettings> rUSettingsEntitity) {
rUSettingsEntitity.HasKey(e => e.RuSettingsId);
rUSettingsEntitity.HasOne(d => d.RegisteredUser).WithMany(p => p.RuSettings).IsRequired();
rUSettingsEntitity.Property(e => e.SettingKey).IsRequired();
rUSettingsEntitity.Property(e => e.SettingValue).IsRequired();
rUSettingsEntitity
.Property(e => e.DataCreationDate)
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("CURRENT_TIMESTAMP")
.ValueGeneratedOnAdd();
rUSettingsEntitity
.Property(e => e.DataModificationDate)
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
.ValueGeneratedOnAddOrUpdate()
.IsConcurrencyToken();
rUSettingsEntitity
.Property(e => e.DataModificationByUser)
.HasColumnType("TINYTEXT")
.HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
rUSettingsEntitity.Property(e => e.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
rUSettingsEntitity.Property(e => e.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken();
rUSettingsEntitity.Property(e => e.DataModificationByUser).HasColumnType("TINYTEXT").HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
}
}

@ -297,7 +297,7 @@ public class GenericImporter
DataStatus = Status.Active.ToString(),
DataValidUntil = farInTheFuture,
DataVersionComment = "Initial Importer by CD-ImporterFomCsv",
Product = new Product(),
// Product = new Product(),
Supplier = new() { AccountName = fields[2] is "" or "RB" ? "Agilent Technologies" : fields[2] }
};
importedCd.DataCreationDate = importedCd.DataValidFrom = importedCd.DataModificationDate = DateTime.Now;
@ -363,12 +363,11 @@ public class GenericImporter
{
//Skip Desciptions, if it has been already imported above (as part from 3PP)
if (thirdPartyProductsFromImportedCDs.Equals(cD.Product)) continue;
// if (thirdPartyProductsFromImportedCDs.Equals(cD.Product)) continue;
//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();
// 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;

@ -3,9 +3,9 @@ using Microsoft.EntityFrameworkCore;
namespace Gremlin_BlazorServer.Data.DBClasses;
public class GremlinDb : DbContext
{
public class GremlinDb : DbContext {
public DbSet<Contact>? Contacts { get; set; }
public DbSet<SalesRep>? SalesReps { get; set; }
public DbSet<Account>? Accounts { get; set; }
public DbSet<Quote>? Quotes { get; set; }
public DbSet<Product>? Products { get; set; }
@ -17,17 +17,16 @@ public class GremlinDb : DbContext
public DbSet<RuSettings>? RuSettings { get; set; }
public DbSet<RegisteredUser>? RegisteredUser { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
const string connectionString = "server=woitschetzki.de;port=3306;database=regulus;user=root;password=lungretter1;SslMode=;SslCa=";
//optionsBuilder.LogTo(Console.WriteLine);
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
// const string connectionString = "server=192.168.177.2;port=3306;database=regulus;user=root;password=lungretter1;SslMode=;SslCa=";
// const string connectionString = "server=server0;port=3306;database=regulus;user=sascha;password=mgltoJtmmDnKJ86LltsGdw";
const string connectionString = "server=woitschetzki.de;port=3306;database=regulus;user=sascha;password=mgltoJtmmDnKJ86LltsGdw;SslMode=;SslCa=";
// optionsBuilder.LogTo(Console.WriteLine);
try
{
try {
optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString), options => options.EnableRetryOnFailure()).EnableSensitiveDataLogging().EnableDetailedErrors();
}
catch (Exception e)
{
catch (Exception e) {
Console.WriteLine(e);
OnConfiguring(optionsBuilder);
throw;
@ -50,8 +49,7 @@ public class GremlinDb : DbContext
// }
// }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
protected override void OnModelCreating(ModelBuilder modelBuilder) {
//wozu dient die folgende Zeile?
base.OnModelCreating(modelBuilder);

@ -17,6 +17,7 @@ public class Account : IMetadata
public AccountType? AccountType { get; set; }
public SubMarket? SubMarket { get; set; }
public IList<Contact>? Contacts { get; set; }
public IList<SalesRep> SalesReps { get; set; }
// public IList<CustomDescription>? CustomDescriptions { get; set; }
//class properties:

@ -11,7 +11,6 @@ public class Contact : IMetadata
//navigation properties:
public Account? Account { get; set; }
public IList<Quote>? Quotes { get; set; }
public IList<Quote>? SalesRepQuotes { get; set; }
//class properties:
public string? AcademicTitle { get; set; }

@ -13,9 +13,8 @@ public class CustomDescription : IMetadata
public uint SupplierId { get; set; }
//navigation properties:
public Product? Product { get; set; }
public Product Product { get; set; }
public Account? Supplier { get; set; }
public IList<LineItem>? LineItems { get; set; }
//class properties:
public string ProductNumber { get; set; } = Empty;

@ -7,11 +7,13 @@ public class LineItem : IMetadata
//foreign keys:
public uint QuoteId { get; set; }
public uint CustomDescriptionId { get; set; }
public uint ProductId { get; set; }
// public uint CustomDescriptionId { get; set; }
//navigation properties:
public Quote? Quote { get; set; }
public CustomDescription? CustomDescription { get; set; }
public Product? Product { get; set; }
// public CustomDescription? CustomDescription { get; set; }
//class properties:
public ushort Position { get; set; }

@ -7,10 +7,12 @@ public class Product : IMetadata
//navigation properties:
public ProductLine? ProductLine { get; set; }
public CustomDescription CustomDescription { get; set; }
public List<LineItem>? LineItems { get; set; }
public CustomDescription? CustomDescription { get; set; }
//foreign keys
public string? ProductLineCode { get; set; }
public uint CustomDescriptionId { get; set; }
//Agilent-specific properties:
public string? ProductNumber { get; set; }

@ -8,10 +8,11 @@ public class Quote : IMetadata
//foreign keys:
public uint RecipientId { get; set; }
public uint SalesRepId { get; set; }
// public uint ProductId { get; set; }
//navigation properties:
public Contact Recipient { get; set; } = new() { Account = new() };
public Contact SalesRep { get; set; } = new() { Account = new() };
public Contact? Recipient { get; set; } = new() { Account = new() };
public SalesRep? SalesRep { get; set; } = new() { Account = new() };
public IList<LineItem>? LineItems { get; set; }

@ -0,0 +1,35 @@
namespace Gremlin_BlazorServer.Data.EntityClasses;
public class SalesRep : IMetadata
{
//primary key:
public uint SalesRepId { get; set; }
//foreign keys:
public uint AccountId { get; set; }
// public uint QuoteId { get; set; }
//navigation properties:
public Account? Account { get; set; }
public IList<Quote>? ListOfQuotes { get; set; }
//class properties:
public string? TerritoryId { get; set; }
public string? AcademicTitle { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
public byte Gender { get; set; }
public string? PhoneNumber { get; set; }
public string? MobileNumber { get; set; }
public string? EMail { get; set; }
//metadata:
public DateTime DataCreationDate { get; set; } = DateTime.Now;
public DateTime DataModificationDate { get; set; } = DateTime.Now;
public DateTime DataValidFrom { get; set; } = DateTime.Now;
public DateTime DataValidUntil { get; set; } = DateTime.MaxValue;
public string DataModificationByUser { get; set; } = "Gremlin_BlazorServer";
public uint DataVersionNumber { get; set; } = 1;
public string? DataVersionComment { get; set; }
public string DataStatus { get; set; } = "Active";
}

@ -5,10 +5,10 @@
@using System.Security.Claims;
@using System.Text;
@inject GenericController genericController
@inject NavigationManager navigationManager
@inject HostingService hostingService
@inject IJSRuntime jSRuntime
@inject GenericController GenericController
@inject NavigationManager NavigationManager
@inject HostingService HostingService
@inject IJSRuntime JsRuntime
@inject ILoadingIndicatorService ApplicationLoadingIndicatorService
<AuthorizeView>
@ -39,7 +39,7 @@
</Paragraph>
</Div>
@if (quote != null)
@if (quote is not null)
{
<Div Margin="Margin.Is3"
Border="Border.Dark.OnAll"
@ -94,7 +94,7 @@
</Field>
</Column>
@if (quote != null && quote.Recipient != null && quote.Recipient.Account != null)
@if (quote?.Recipient?.Account is not null)
{
<Column ColumnSize="ColumnSize.Is3">
<Field>
@ -174,7 +174,7 @@
</Div>
}
@if (quote != null && quote.LineItems != null) {
@if (quote?.LineItems is not null) {
<Div Margin="Margin.Is3"
Border="Border.Dark.OnAll"
Padding="Padding.Is3"
@ -200,7 +200,7 @@
</Paragraph>
</Div>
@if (selectedLineItem != null && selectedLineItem.CustomDescription != null) {
@if (selectedLineItem?.Product?.CustomDescription is not null) {
<Div Margin="Margin.Is3"
Border="Border.Dark.OnAll"
Padding="Padding.Is3"
@ -210,7 +210,7 @@
<Paragraph>
<Field>
<FieldLabel ColumnSize="ColumnSize.Is1">ProductNumber</FieldLabel>
<FieldBody ColumnSize="ColumnSize.Is11">@selectedLineItem.CustomDescription.ProductNumber</FieldBody>
<FieldBody ColumnSize="ColumnSize.Is11">@selectedLineItem.Product.CustomDescription.ProductNumber</FieldBody>
</Field>
<Field>
<FieldLabel ColumnSize="ColumnSize.Is1">OptionNumber</FieldLabel>
@ -218,22 +218,22 @@
</Field>
<Field>
<FieldLabel ColumnSize="ColumnSize.Is1">Heading</FieldLabel>
<FieldBody ColumnSize="ColumnSize.Is11">@selectedLineItem.CustomDescription.Heading</FieldBody>
<FieldBody ColumnSize="ColumnSize.Is11">@selectedLineItem.Product.CustomDescription.Heading</FieldBody>
</Field>
<Field>
<FieldLabel ColumnSize="ColumnSize.Is1">CoverletterText</FieldLabel>
<FieldBody ColumnSize="ColumnSize.Is11">@selectedLineItem.CustomDescription.CoverletterText</FieldBody>
<FieldBody ColumnSize="ColumnSize.Is11">@selectedLineItem.Product.CustomDescription.CoverletterText</FieldBody>
</Field>
<Field>
<FieldLabel ColumnSize="ColumnSize.Is1">DescriptionText</FieldLabel>
<FieldBody ColumnSize="ColumnSize.Is11">@selectedLineItem.CustomDescription.DescriptionText</FieldBody>
<FieldBody ColumnSize="ColumnSize.Is11">@selectedLineItem.Product.CustomDescription.DescriptionText</FieldBody>
</Field>
</Paragraph>
</Div>
}
}
@if (quote != null && quote.LineItems == null) {
@if (quote is {LineItems: null }) {
<Div Margin="Margin.Is3"
Border="Border.Dark.OnAll"
Padding="Padding.Is3"

@ -1,135 +1,107 @@
using System.Diagnostics;
using System.Globalization;
using System.Security.Claims;
using System.Text;
using Blazorise;
using Gremlin_BlazorServer.Data.EntityClasses;
using Gremlin_BlazorServer.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.JSInterop;
using System.Diagnostics;
using System.Globalization;
using System.Security.Claims;
using System.Text;
namespace Gremlin_BlazorServer.Pages.Quotes;
public partial class QuoteAdd
{
[CascadingParameter] private Task<AuthenticationState>? AuthenticationStateTask { get; set; }
[Inject] public IModalService? ModalService { get; set; }
public partial class QuoteAdd {
private readonly CultureInfo cultureInfo = new("de-DE");
private readonly bool debug;
private IList<Contact>? contacts;
private Quote? quote;
private Contact? selectedContact;
private readonly CultureInfo cultureInfo = new("de-DE");
private bool pdfNotReady = true;
private bool isCreatingPdf;
private bool texNotReady = true;
private bool isCreatingTex;
private bool lineItemsNotReady = true;
private string? url;
private readonly bool debug;
private List<CustomDescription>? suggestedCustomDescriptions;
private CustomDescription? newCustomDescription;
private bool pdfNotReady = true;
private Quote quote = new();
private Contact? selectedContact;
private LineItem? selectedLineItem;
private List<CustomDescription>? suggestedCustomDescriptions;
private bool texNotReady = true;
private string? url;
[CascadingParameter] private Task<AuthenticationState>? AuthenticationStateTask { get; set; }
[Inject] public IModalService? ModalService { get; set; }
public Task ShowCustomDescriptionModal() =>
ModalService.Show<CustomDescriptionModal>(builder =>
{
public Task ShowCustomDescriptionModal() {
return ModalService.Show<CustomDescriptionModal>(builder => {
builder.Add(parameter => parameter.CustomDescription, newCustomDescription);
builder.Add(parameter => parameter.SuggestedCustomDescriptions, suggestedCustomDescriptions);
});
}
protected override async Task OnParametersSetAsync()
{
if (AuthenticationStateTask != null)
{
protected override async Task OnParametersSetAsync() {
if (AuthenticationStateTask is not null) {
ClaimsPrincipal user = (await AuthenticationStateTask).User;
if (user.Identity is { IsAuthenticated: true })
{
await ApplicationLoadingIndicatorService.Show();
contacts = await genericController.GetAllAsync<Contact>();
await ApplicationLoadingIndicatorService.Hide();
quote = await GenerateNewQuote(quote, "Woitschetzki");
if (user.Identity is { IsAuthenticated: true }) {
contacts = await GenericController.GetAllAsync<Contact>();
selectedContact = contacts?.FirstOrDefault();
if (selectedContact is not null)
await OnSelectedContactChanged(selectedContact);
SalesRep newSalesRep = new() {
LastName = "Woitschetzki",
FirstName = "Sascha",
TerritoryId = "83PE89",
PhoneNumber = "+49 176 22285334",
EMail = "sascha.woitschetzki@non.agilent.com",
AccountId = 2262,
Gender = 1
};
quote = await GenerateNewQuote(quote, newSalesRep);
}
}
await base.OnInitializedAsync();
}
private async Task<Quote> GenerateNewQuote(Quote? _quote, string salesRepLastName)
{
if (_quote == null)
{
_quote = new();
_ = await genericController.InsertAsync(_quote);
}
private async Task<Quote> GenerateNewQuote(Quote newQuote, SalesRep newSalesRep) {
newQuote.SalesRep = newSalesRep; //await genericController.GetAsync<SalesRep>(sR => sR.LastName.Equals(newSalesRep.LastName));
newQuote.SalesRep.Account = await GenericController.GetAsync<Account>(a => a.AccountId.Equals(newQuote.SalesRep.AccountId));
_quote.SalesRep = await genericController.GetAsync<Contact>(c => c.LastName == salesRepLastName);
if (_quote.SalesRep != null)
//Read Account seperatly to avoid new creation of account
_quote.SalesRep.Account = await genericController.GetAsync<Account>(a => a.AccountId == _quote.SalesRep.AccountId);
Quote? lastQuote = GenericController.GetLast<Quote>();
newQuote.QuoteId = lastQuote is not null ? lastQuote.QuoteId + 1 : 1;
newQuote.QuotationNumber = $"DE-{newQuote.SalesRep?.TerritoryId}-{DateTime.Now:My}-{newQuote.QuoteId}";
newQuote.Description = "Gerät";
await TryToSaveQuote(newQuote);
Quote? lastQuote = genericController.GetLast<Quote>();
_quote.QuoteId = lastQuote != null ? lastQuote.QuoteId + 1 : 1;
_quote.QuotationNumber = _quote.SalesRep != null ? _quote.SalesRep.LastName switch
{
"Woitschetzki" => $"DE-83PE89-{DateTime.Now:My}-{_quote.QuoteId}",
"Welsch" => $"DE-83RE32-{DateTime.Now:My}-{_quote.QuoteId}",
_ => $"DE-XXYYXX-{DateTime.Now:My}-{_quote.QuoteId}"
return newQuote;
}
: $"DE-XXYYXX-{DateTime.Now:My}-{_quote.QuoteId}";
_quote.Description = "Gerät";
_ = TryToSaveQuote(_quote);
return _quote;
private async Task TryToSaveQuote(Quote newQuote) {
Debug.WriteLine(await GenericController.UpdateAsync(newQuote) > 0 ? "Speichern der Quote erfolgreich." : "Fehler beim Speichern der Quote!");
}
private async Task TryToSaveQuote(Quote _quote)
{
if (await genericController.UpdateAsync(_quote) > 0)
Debug.WriteLine("Speichern der Quote erfolgreich.");
else
Debug.WriteLine("Fehler beim Speichern der Quote!");
return;
}
private async Task SelectQuoteOnChanged(FileChangedEventArgs e)
{
try
{
foreach (IFileEntry? file in e.Files)
{
private async Task SelectQuoteOnChanged(FileChangedEventArgs e) {
try {
foreach (IFileEntry? file in e.Files) {
using MemoryStream stream = new();
await file.WriteToStreamAsync(stream);
_ = stream.Seek(0, SeekOrigin.Begin);
using StreamReader reader = new(stream);
string fileContent = await reader.ReadToEndAsync();
quote = QuoteHandling.ReadLineItems(quote, fileContent);
if (quote.Recipient?.Account?.AccountName != null) quote = hostingService.SetPath(quote);
if (quote.LineItems == null) return;
if (quote.Recipient?.Account?.AccountName is not null) quote = HostingService.SetPath(quote);
if (quote.LineItems is null) return;
FileService.WriteQuoteToTsv(fileContent, quote);
//TODO Load all relevant CustomDescriptions upfront
for (int i = 0; i < quote.LineItems.Count; i++)
{
newCustomDescription = await genericController.GetAsync<CustomDescription>(
newCustomDescription => newCustomDescription.ProductNumber.Equals(quote.LineItems[i].ProductNumber, StringComparison.Ordinal)
&& newCustomDescription.OptionNumber.Equals(quote.LineItems[i].OptionNumber, StringComparison.Ordinal)
);
if (newCustomDescription == null)
{
Console.WriteLine($"Keine CustomDescription für {quote.LineItems[i].ProductNumber}#{quote.LineItems[i].OptionNumber} verfügbar!");
suggestedCustomDescriptions = await SuggestCustomDescriptions(quote.LineItems[i]);
newCustomDescription = new()
{
ProductNumber = quote.LineItems[i].ProductNumber,
OptionNumber = quote.LineItems[i].OptionNumber,
Heading = quote.LineItems[i].SapShortDescription,
DescriptionText = quote.LineItems[i].SapLongDescription
};
foreach (LineItem lineItem in quote.LineItems) {
newCustomDescription = await GenericController.GetAsync<CustomDescription>(newCustomDescription => newCustomDescription.ProductNumber.Equals(lineItem.ProductNumber, StringComparison.Ordinal) && newCustomDescription.OptionNumber.Equals(lineItem.OptionNumber, StringComparison.Ordinal));
if (newCustomDescription is null) {
Console.WriteLine($"Keine CustomDescription für {lineItem.ProductNumber}#{lineItem.OptionNumber} verfügbar!");
suggestedCustomDescriptions = await SuggestCustomDescriptions(lineItem);
newCustomDescription = new() { ProductNumber = lineItem.ProductNumber, OptionNumber = lineItem.OptionNumber, Heading = lineItem.SapShortDescription, DescriptionText = lineItem.SapLongDescription };
//Show windows to edit new cD
await ShowCustomDescriptionModal();
@ -137,31 +109,33 @@ public partial class QuoteAdd
//Insert new CustomDescription to db
newCustomDescription.AccountId = 1;
_ = await genericController.InsertAsync(newCustomDescription);
_ = await GenericController.InsertAsync(newCustomDescription);
}
//read cD form db to cleanup ChangeTracker
quote.LineItems[i].CustomDescription = await genericController.GetAsync<CustomDescription>(cD => cD.CustomDescriptionId.Equals(newCustomDescription.CustomDescriptionId));
lineItem.Product = new() {
ProductNumber = lineItem.ProductNumber,
OptionNumber = lineItem.OptionNumber,
CustomDescription = await GenericController.GetAsync<CustomDescription>(cD => cD.ProductNumber.Equals(lineItem.ProductNumber) && cD.OptionNumber.Equals(lineItem.OptionNumber))
};
// lineItem.Product = await GenericController.GetAsync<Product>(p => p.ProductNumber.Equals(lineItem.ProductNumber) && p.OptionNumber.Equals(lineItem.OptionNumber), "CustomDescription");
// quote.LineItems[i].Product.CustomDescription = await genericController.GetAsync<CustomDescription>(cD => cD.CustomDescriptionId.Equals(newCustomDescription.CustomDescriptionId));
}
}
}
catch (Exception exc)
{
catch (Exception exc) {
Console.WriteLine(exc.Message);
}
finally
{
finally {
if (quote.Recipient != null) lineItemsNotReady = false;
StateHasChanged();
}
}
private async Task<List<CustomDescription>?> SuggestCustomDescriptions(LineItem lineItem)
{
private async Task<List<CustomDescription>?> SuggestCustomDescriptions(LineItem lineItem) {
//IList<CustomDescription>? fromProductNumber = await genericController.GetAllAsync<CustomDescription>(cD => cD.ProductNumber.Equals(lineItem.ProductNumber, StringComparison.Ordinal));
IList<CustomDescription>? fromOptionNumber = new List<CustomDescription>();
if (lineItem.OptionNumber != "")
fromOptionNumber = await genericController.GetAllAsync<CustomDescription>(cD => cD.OptionNumber.Equals(lineItem.OptionNumber, StringComparison.Ordinal));
fromOptionNumber = await GenericController.GetAllAsync<CustomDescription>(cD => cD.OptionNumber.Equals(lineItem.OptionNumber, StringComparison.Ordinal));
//if (fromOptionNumber == null && fromProductNumber == null) return null;
//if (fromOptionNumber == null) return fromProductNumber.ToList();
//if (fromProductNumber == null) return fromOptionNumber.ToList();
@ -169,39 +143,37 @@ public partial class QuoteAdd
return fromOptionNumber.ToList();
}
private static void SelectQuoteOnWritten(FileWrittenEventArgs e) =>
private static void SelectQuoteOnWritten(FileWrittenEventArgs e) {
Console.WriteLine($"File: {e.File.Name} Position: {e.Position} Data: {Convert.ToBase64String(e.Data)}");
}
private static void SelectQuoteOnProgressed(FileProgressedEventArgs e) =>
private static void SelectQuoteOnProgressed(FileProgressedEventArgs e) {
Console.WriteLine($"File: {e.File.Name} Progress: {e.Percentage}");
}
private async Task OnSelectedContactChanged(Contact _selectedContact)
{
if (quote == null) return;
quote.Recipient = await genericController.GetAsync<Contact>(c => c.ContactId.Equals(_selectedContact.ContactId));
private async Task OnSelectedContactChanged(Contact newSelectedContact) {
quote.Recipient = await GenericController.GetAsync<Contact>(c => c.ContactId.Equals(newSelectedContact.ContactId));
if (quote.Recipient != null)
if (quote.Recipient is not null)
//Read account seperatly to avoid new generation
quote.Recipient.Account = await genericController.GetAsync<Account>(a => a.AccountId.Equals(quote.Recipient.AccountId));
quote.Recipient.Account = await GenericController.GetAsync<Account>(a => a.AccountId.Equals(quote.Recipient.AccountId));
if (quote.LineItems != null && quote.Recipient != null && quote.Recipient.Account != null) lineItemsNotReady = false;
if (quote is { LineItems: not null, Recipient.Account: not null }) lineItemsNotReady = false;
selectedContact = _selectedContact;
selectedContact = newSelectedContact;
}
private async Task OnSave()
{
private async Task OnSave() {
//HACK Try to avoid new generation of FKs
// quote.Recipient = new() { Account = new() };
// quote.SalesRep = new() { Account = new() };
// quote.LineItems = null;
if (await genericController.UpdateAsync(quote) > 0)
navigationManager.NavigateTo("Quotes/QuoteIndex");
if (await GenericController.UpdateAsync(quote) > 0)
NavigationManager.NavigateTo("Quotes/QuoteIndex");
}
private async Task OnCreateTex()
{
private async Task OnCreateTex() {
isCreatingTex = true;
StringBuilder? tex = await QuoteHandling.CreateTexAsync(quote);
@ -216,11 +188,9 @@ public partial class QuoteAdd
texNotReady = false;
}
private async Task OnCreatePdf()
{
private async Task OnCreatePdf() {
isCreatingPdf = true;
if (await PdfService.CreatePdf(quote))
{
if (await PdfService.CreatePdf(quote)) {
pdfNotReady = false;
isCreatingPdf = false;
Console.WriteLine("PDF successfull written.");
@ -229,34 +199,55 @@ public partial class QuoteAdd
}
}
private void OnOpenPdfApp() => PdfService.OpenPdfWithOkular(quote);
private void OnOpenPdfApp() {
PdfService.OpenPdfWithOkular(quote);
}
private async Task OnOpenPdfNewTab() =>
await jSRuntime.InvokeVoidAsync("OpenNewTab", $"quotes/{url}");
private async Task OnOpenPdfNewTab() {
await JsRuntime.InvokeVoidAsync("OpenNewTab", $"quotes/{url}");
}
private void OnDescriptionChanged(string description) => quote.Description = description;
private void OnDescriptionChanged(string description) {
quote.Description = description;
}
private void OnQuotationNumberChanged(string quotationNumber) =>
private void OnQuotationNumberChanged(string quotationNumber) {
quote.QuotationNumber = quotationNumber;
}
private void OnValidForChanged(string validFor) => quote.ValidFor = byte.Parse(validFor);
private void OnValidForChanged(string validFor) {
quote.ValidFor = byte.Parse(validFor);
}
private void OnVATChanged(string vat) => quote.Vat = float.Parse(vat);
private void OnVATChanged(string vat) {
quote.Vat = float.Parse(vat);
}
private void OnIsPriceInformationChanged(bool isPriceInformation) =>
private void OnIsPriceInformationChanged(bool isPriceInformation) {
quote.IsPriceInformation = isPriceInformation;
}
private void OnShowBruttoChanged(bool onShowBrutto) => quote.ShowBrutto = onShowBrutto;
private void OnShowBruttoChanged(bool onShowBrutto) {
quote.ShowBrutto = onShowBrutto;
}
private void OnShowDiscountsChanged(bool showDiscount) => quote.ShowDiscounts = showDiscount;
private void OnShowDiscountsChanged(bool showDiscount) {
quote.ShowDiscounts = showDiscount;
}
private void OnShowSinglePricesChanged(bool showSinglePrices) =>
private void OnShowSinglePricesChanged(bool showSinglePrices) {
quote.ShowSinglePrices = showSinglePrices;
}
private void OnSelectedLineItemChanged(LineItem _selectedLineItem) =>
private void OnSelectedLineItemChanged(LineItem _selectedLineItem) {
selectedLineItem = _selectedLineItem;
}
private void OnWarrantyChanged(string warranty) => quote.Warranty = int.Parse(warranty);
private void OnWarrantyChanged(string warranty) {
quote.Warranty = int.Parse(warranty);
}
private void OnCancel() => navigationManager.NavigateTo("Quotes/QuoteIndex");
private void OnCancel() {
NavigationManager.NavigateTo("Quotes/QuoteIndex");
}
}

@ -2,9 +2,6 @@ using Blazorise;
using Blazorise.Icons.Material;
using Blazorise.LoadingIndicator;
using Blazorise.Material;
//using Blazorise.Bootstrap;
//using Blazorise.Icons.FontAwesome;
using Gremlin_BlazorServer.Areas.Identity;
using Gremlin_BlazorServer.Data;
using Gremlin_BlazorServer.Data.DBClasses;
@ -12,6 +9,9 @@ using Gremlin_BlazorServer.Services;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using GenericImporter = Gremlin_BlazorServer.Services.GenericImporter;
//using Blazorise.Bootstrap;
//using Blazorise.Icons.FontAwesome;
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
@ -22,33 +22,23 @@ builder.Services.AddServerSideBlazor();
builder.Services.AddScoped<GremlinDb>();
builder.Services.AddScoped<GenericController>();
builder.Services.AddScoped<HostingService>();
builder.Services.AddScoped<Gremlin_BlazorServer.Services.GenericImporter>();
builder.Services.AddScoped<GenericImporter>();
builder.Services.AddBlazorise(options => { options.Immediate = true; })
//.AddBootstrapProviders()
//.AddBootstrapComponents()
//.AddFontAwesomeIcons()
.AddMaterialProviders()
.AddMaterialIcons();
.AddMaterialProviders().AddMaterialIcons();
builder.Services.AddOptions();
builder.Services.AddLoadingIndicator();
//Auth
const string connection = "server0";
string connectionString =
builder.Configuration.GetConnectionString(connection)
?? throw new InvalidOperationException($"Connection string '{connection}' not found.");
string connectionString = builder.Configuration.GetConnectionString(connection) ?? throw new InvalidOperationException($"Connection string '{connection}' not found.");
ServerVersion serverVersion = ServerVersion.AutoDetect(connectionString);
builder.Services.AddDbContext<BlazorAuthDb>(
options => options.UseMySql(connectionString, serverVersion)
);
builder.Services
.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<BlazorAuthDb>();
builder.Services.AddScoped<
AuthenticationStateProvider,
RevalidatingIdentityAuthenticationStateProvider<IdentityUser>
>();
builder.Services.AddDbContext<BlazorAuthDb>(options => options.UseMySql(connectionString, serverVersion));
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true).AddEntityFrameworkStores<BlazorAuthDb>();
builder.Services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();
builder.Services.AddControllersWithViews();
//
@ -61,8 +51,7 @@ builder.WebHost.UseUrls("https://*:5000");
WebApplication app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
if (!app.Environment.IsDevelopment()) {
_ = app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
_ = app.UseHsts();

@ -1,32 +1,24 @@
using Gremlin_BlazorServer.Data.EntityClasses;
using System.Reflection;
using System.Reflection;
using System.Text;
using Gremlin_BlazorServer.Data.EntityClasses;
namespace Gremlin_BlazorServer.Services;
internal static class FileService
{
internal static class FileService {
private static readonly Encoding defaultEncodingIfNoBom = Encoding.UTF8;
public static string ReadResource(string name)
{
public static string ReadResource(string name) {
Assembly assembly = Assembly.GetExecutingAssembly();
// Format: "{Namespace}.{Folder}.{filename}.{Extension}"
string resourcePath = name.StartsWith(nameof(Gremlin_BlazorServer))
? name
: assembly.GetManifestResourceNames().Single(str => str.EndsWith(name));
string resourcePath = name.StartsWith(nameof(Gremlin_BlazorServer)) ? name : assembly.GetManifestResourceNames().Single(str => str.EndsWith(name));
using Stream? stream = assembly.GetManifestResourceStream(resourcePath);
if (stream == null)
{
return "";
}
if (stream is null) return "";
using StreamReader reader = new(stream);
return reader.ReadToEnd();
}
public static Encoding GetEncoding(string fileName)
{
public static Encoding GetEncoding(string fileName) {
Stream fileStream = File.OpenRead(fileName);
using StreamReader reader = new(fileStream, defaultEncodingIfNoBom, true);
_ = reader.Peek();
@ -34,25 +26,17 @@ internal static class FileService
return encoding;
}
public static void WriteQuoteToTsv(string quoteContent, Quote quote)
{
public static void WriteQuoteToTsv(string quoteContent, Quote quote) {
string datei = $"{quote.Path}{Path.DirectorySeparatorChar}{quote.QuotationNumber}.tsv";
FileInfo fileInfo = new(datei);
if (fileInfo.Directory == null)
{
return;
}
if (fileInfo.Directory is null) return;
if (!fileInfo.Directory.Exists)
{
try
{
try {
_ = Directory.CreateDirectory(fileInfo.DirectoryName ?? "");
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
catch (Exception ex) {
Console.WriteLine(ex.InnerException);
}
using StreamWriter writer = new(datei, false, Encoding.UTF8);
@ -61,21 +45,14 @@ internal static class FileService
}
}
public static async Task WriteTexFile(Quote quote)
{
public static async Task WriteTexFile(Quote quote) {
string datei = $"{quote.Path}{Path.DirectorySeparatorChar}{quote.QuotationNumber}.tex";
FileInfo fileInfo = new(datei);
if (fileInfo.Directory == null)
{
return;
}
if (fileInfo.Directory == null) return;
if (!fileInfo.Directory.Exists)
{
_ = Directory.CreateDirectory(fileInfo.DirectoryName ?? "");
}
if (!fileInfo.Directory.Exists) _ = Directory.CreateDirectory(fileInfo.DirectoryName ?? "");
using StreamWriter writer = new(datei, false, Encoding.UTF8);
await using StreamWriter writer = new(datei, false, Encoding.UTF8);
{
await writer.WriteLineAsync(quote.Tex);
}

@ -1,482 +1,331 @@
using Gremlin_BlazorServer.Data.DBClasses;
using Gremlin_BlazorServer.Data.EntityClasses;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
namespace Gremlin_BlazorServer.Services;
public class GenericController
{
public IList<TResult>? GetAll<TResult>()
where TResult : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public class GenericController {
public IList<TResult>? GetAll<TResult>() where TResult : class, IMetadata {
try {
using (GremlinDb gremlinDb = new()) {
return gremlinDb.Set<TResult>().ToList();
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return null;
}
}
public IList<TResult>? GetAll<TResult>(string include)
where TResult : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public IList<TResult>? GetAll<TResult>(string include) where TResult : class, IMetadata {
try {
using (GremlinDb gremlinDb = new()) {
return gremlinDb.Set<TResult>().Include(include).ToList();
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return null;
}
}
public IList<TResult>? GetAll<TResult>(Predicate<TResult> search)
where TResult : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public IList<TResult>? GetAll<TResult>(Predicate<TResult> search) where TResult : class, IMetadata {
ArgumentNullException.ThrowIfNull(search);
try {
using (GremlinDb gremlinDb = new()) {
return gremlinDb.Set<TResult>().AsEnumerable().Where(t => search(t)).ToList();
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return null;
}
}
public async Task<IList<TResult>?> GetAllAsync<TResult>()
where TResult : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public async Task<IList<TResult>?> GetAllAsync<TResult>() where TResult : class, IMetadata {
try {
await using (GremlinDb gremlinDb = new()) {
return await gremlinDb.Set<TResult>().ToListAsync();
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return null;
}
}
public async Task<IList<TResult>?> GetAllAsync<TResult>(string include)
where TResult : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public async Task<IList<TResult>?> GetAllAsync<TResult>(string include) where TResult : class, IMetadata {
try {
await using (GremlinDb gremlinDb = new()) {
return await gremlinDb.Set<TResult>().Include(include).ToListAsync();
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return null;
}
}
public async Task<IList<TResult>?> GetAllAsync<TResult>(string include1, string include2)
where TResult : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
return await gremlinDb
.Set<TResult>()
.Include(include1)
.Include(include2)
.ToListAsync();
}
}
catch (Exception exception)
{
public async Task<IList<TResult>?> GetAllAsync<TResult>(string include1, string include2) where TResult : class, IMetadata {
try {
await using (GremlinDb gremlinDb = new()) {
return await gremlinDb.Set<TResult>().Include(include1).Include(include2).ToListAsync();
}
}
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return null;
}
}
public async Task<IList<TResult>?> GetAllAsync<TResult>(Predicate<TResult> search)
where TResult : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
return await Task.Run(
() => gremlinDb.Set<TResult>().AsEnumerable().Where(t => search(t)).ToList()
);
}
}
catch (Exception exception)
{
public async Task<IList<TResult>?> GetAllAsync<TResult>(Predicate<TResult> search) where TResult : class, IMetadata {
ArgumentNullException.ThrowIfNull(search);
try {
await using (GremlinDb gremlinDb = new()) {
return await Task.Run(() => gremlinDb.Set<TResult>().AsEnumerable().Where(t => search(t)).ToList());
}
}
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return null;
}
}
public async Task<IList<TResult>?> GetAllAsync<TResult>(
Predicate<TResult> search,
string include
)
where TResult : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
return await Task.Run(
() =>
gremlinDb
.Set<TResult>()
.Include(include)
.AsEnumerable()
.Where(t => search(t))
.ToList()
);
}
}
catch (Exception exception)
{
public async Task<IList<TResult>?> GetAllAsync<TResult>(Predicate<TResult> search, string include) where TResult : class, IMetadata {
ArgumentNullException.ThrowIfNull(search);
try {
await using (GremlinDb gremlinDb = new()) {
return await Task.Run(() => gremlinDb.Set<TResult>().Include(include).AsEnumerable().Where(t => search(t)).ToList());
}
}
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return null;
}
}
public IList<TResult>? GetAll<TResult>(Predicate<TResult> search, string include)
where TResult : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
return gremlinDb
.Set<TResult>()
.Include(include)
.AsEnumerable()
.Where(t => search(t))
.ToList();
}
}
catch (Exception exception)
{
public IList<TResult>? GetAll<TResult>(Predicate<TResult> search, string include) where TResult : class, IMetadata {
ArgumentNullException.ThrowIfNull(search);
try {
using (GremlinDb gremlinDb = new()) {
return gremlinDb.Set<TResult>().Include(include).AsEnumerable().Where(t => search(t)).ToList();
}
}
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return null;
}
}
public TResult? Get<TResult>(Predicate<TResult> search)
where TResult : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public TResult? Get<TResult>(Predicate<TResult> search) where TResult : class, IMetadata {
ArgumentNullException.ThrowIfNull(search);
try {
using (GremlinDb gremlinDb = new()) {
return gremlinDb.Set<TResult>().AsEnumerable().FirstOrDefault(t => search(t));
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return null;
}
}
public async Task<TResult?> GetAsync<TResult>(Predicate<TResult> search) where TResult : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public async Task<TResult?> GetAsync<TResult>(Predicate<TResult> search) where TResult : class, IMetadata {
ArgumentNullException.ThrowIfNull(search);
try {
await using (GremlinDb gremlinDb = new()) {
return await Task.Run(() => gremlinDb.Set<TResult>().AsEnumerable().FirstOrDefault(t => search(t)));
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return null;
}
}
public TResult? Get<TResult>(Predicate<TResult> search, string include) where TResult : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public TResult? Get<TResult>(Predicate<TResult> search, string include) where TResult : class, IMetadata {
ArgumentNullException.ThrowIfNull(search);
try {
using (GremlinDb gremlinDb = new()) {
return gremlinDb.Set<TResult>().AsNoTracking().Include(include).AsEnumerable().FirstOrDefault(t => search(t));
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return null;
}
}
public async Task<TResult?> GetAsync<TResult>(Predicate<TResult> search, string include1)
where TResult : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public async Task<TResult?> GetAsync<TResult>(Predicate<TResult> search, string include1) where TResult : class, IMetadata {
ArgumentNullException.ThrowIfNull(search);
try {
await using (GremlinDb gremlinDb = new()) {
return await Task.Run(() => gremlinDb.Set<TResult>().Include(include1).AsEnumerable().FirstOrDefault(t => search(t)));
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return null;
}
}
public async Task<TResult?> GetAsync<TResult>(
Predicate<TResult> search,
string include1,
string include2
)
where TResult : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
return await Task.Run(
() =>
gremlinDb
.Set<TResult>()
.Include(include1)
.Include(include2)
.AsEnumerable()
.FirstOrDefault(t => search(t))
);
}
}
catch (Exception exception)
{
public async Task<TResult?> GetAsync<TResult>(Predicate<TResult> search, string include1, string include2) where TResult : class, IMetadata {
ArgumentNullException.ThrowIfNull(search);
try {
await using (GremlinDb gremlinDb = new()) {
return await Task.Run(() => gremlinDb.Set<TResult>().Include(include1).Include(include2).AsEnumerable().FirstOrDefault(t => search(t)));
}
}
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return null;
}
}
public TResult? GetLast<TResult>()
where TResult : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public TResult? GetLast<TResult>() where TResult : class, IMetadata {
try {
using (GremlinDb gremlinDb = new()) {
return gremlinDb.Set<TResult>().AsEnumerable().Last();
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return null;
}
}
public int Insert<T>(T entity)
where T : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public int Insert<T>(T entity) where T : class, IMetadata {
try {
using (GremlinDb gremlinDb = new()) {
gremlinDb.Set<T>().Add(entity);
return gremlinDb.SaveChanges();
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return 0;
}
}
public int Insert<T>(List<T> entities)
where T : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public int Insert<T>(IEnumerable<T> entities) where T : class, IMetadata {
try {
using (GremlinDb gremlinDb = new()) {
gremlinDb.Set<T>().AddRange(entities);
return gremlinDb.SaveChanges();
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return 0;
}
}
public async Task<int> InsertAsync<T>(T entity) where T : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public async Task<int> InsertAsync<T>(T entity) where T : class, IMetadata {
try {
await using (GremlinDb gremlinDb = new()) {
gremlinDb.Set<T>().Add(entity);
//DEBUG
var changedEntries = gremlinDb.ChangeTracker.Entries().ToList();
foreach (var changedEntry in changedEntries)
List<EntityEntry> changedEntries = gremlinDb.ChangeTracker.Entries().ToList();
foreach (EntityEntry changedEntry in changedEntries)
Console.WriteLine(changedEntry);
return await gremlinDb.SaveChangesAsync();
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return 0;
}
}
public async Task<int> InsertAsync<T>(List<T> entities)
where T : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public async Task<int> InsertAsync<T>(IEnumerable<T> entities) where T : class, IMetadata {
try {
await using (GremlinDb gremlinDb = new()) {
gremlinDb.Set<T>().AddRange(entities);
return await gremlinDb.SaveChangesAsync();
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return 0;
}
}
public bool IsExisting<T>(Predicate<T> search)
where T : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public static bool IsExisting<T>(Predicate<T> search) where T : class, IMetadata {
ArgumentNullException.ThrowIfNull(search);
try {
using (GremlinDb gremlinDb = new()) {
return gremlinDb.Set<T>().AsEnumerable().Any(t => search(t));
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return false;
}
}
public int Update<T>(T entity)
where T : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public int Update<T>(T entity) where T : class, IMetadata {
try {
using (GremlinDb gremlinDb = new()) {
gremlinDb.Set<T>().Update(entity);
return gremlinDb.SaveChanges();
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return 0;
}
}
public async Task<int> UpdateAsync<T>(T entity) where T : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public async Task<int> UpdateAsync<T>(T entity) where T : class, IMetadata {
try {
await using (GremlinDb gremlinDb = new()) {
gremlinDb.Set<T>().Update(entity);
//DEBUG
var changedEntries = gremlinDb.ChangeTracker.Entries().ToList();
foreach (var changedEntry in changedEntries)
Console.WriteLine(changedEntry);
return await gremlinDb.SaveChangesAsync();
return await gremlinDb.SaveChangesAsync(false);
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return 0;
}
}
public int Update<T>(List<T> entities)
where T : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public int Update<T>(IEnumerable<T> entities) where T : class, IMetadata {
try {
using (GremlinDb gremlinDb = new()) {
gremlinDb.Set<T>().UpdateRange(entities);
return gremlinDb.SaveChanges();
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return 0;
}
}
public async Task<int> UpdateAsync<T>(List<T> entities)
where T : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public async Task<int> UpdateAsync<T>(IEnumerable<T> entities) where T : class, IMetadata {
try {
await using (GremlinDb gremlinDb = new()) {
gremlinDb.Set<T>().UpdateRange(entities);
return await gremlinDb.SaveChangesAsync();
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return 0;
}
}
public async Task<int> RemoveAsync<T>(T entity)
where T : class, IMetadata
{
try
{
using (GremlinDb gremlinDb = new())
{
public async Task<int> RemoveAsync<T>(T entity) where T : class, IMetadata {
try {
await using (GremlinDb gremlinDb = new()) {
gremlinDb.Set<T>().Remove(entity);
return await gremlinDb.SaveChangesAsync();
}
}
catch (Exception exception)
{
catch (Exception exception) {
Console.WriteLine(exception.InnerException);
return 0;
}

@ -118,6 +118,6 @@ public class GenericImporter
private bool AccountExists(uint sapAccountNumber)
{
return genericController.IsExisting<Account>(a => a.SapAccountNumber == sapAccountNumber);
return GenericController.IsExisting<Account>(a => a.SapAccountNumber == sapAccountNumber);
}
}

@ -1,33 +1,24 @@
using Gremlin_BlazorServer.Data.EntityClasses;
using System.Globalization;
using System.Text;
using Gremlin_BlazorServer.Data.EntityClasses;
namespace Gremlin_BlazorServer.Services;
public static class QuoteHandling
{
public static async Task<StringBuilder?> CreateTexAsync(Quote quote)
{
public static class QuoteHandling {
private static GenericController genericController = new();
public static async Task<StringBuilder?> CreateTexAsync(Quote quote) {
StringBuilder? texString = await TexService.CreateTex(quote);
if (texString == null)
{
return null;
}
if (texString is null) return null;
Console.WriteLine(
texString.Length > 0
? "Creating TexFile succesfully."
: "Error during TexFile creation!"
);
Console.WriteLine(texString.Length > 0 ? "Creating TexFile succesfully." : "Error during TexFile creation!");
return texString;
}
//FromWindowsGremlin
public static Quote ReadLineItems(Quote quote, string clipboard)
{
try
{
public static Quote ReadLineItems(Quote quote, string clipboard) {
try {
quote = ResetTotals(quote);
quote.LineItems = ReadLineItemsFromClipboard(clipboard);
@ -39,25 +30,14 @@ public static class QuoteHandling
quote.TotalDiscount = GetTotal(quote, "AverageDiscount");
quote.TotalNet = GetTotal(quote, "TotalNet");
if (quote.Recipient?.Account != null)
{
quote.ValidFor = CheckForAcademic(quote.Recipient.Account);
}
if (quote.Recipient?.Account != null) quote.ValidFor = CheckForAcademic(quote.Recipient.Account);
foreach (LineItem lineItem in quote.LineItems)
{
if (lineItem.OptionNumber == null)
{
break;
}
foreach (LineItem lineItem in quote.LineItems) {
if (lineItem.OptionNumber == null) break;
if (lineItem.OptionNumber.StartsWith("8D"))
{
quote.Warranty = int.Parse(lineItem.OptionNumber.Last().ToString()) * 12;
}
if (lineItem.OptionNumber.StartsWith("8D")) quote.Warranty = int.Parse(lineItem.OptionNumber.Last().ToString()) * 12;
quote.Warranty = lineItem.OptionNumber switch
{
quote.Warranty = lineItem.OptionNumber switch {
"9EC" => 24,
"9CC" => 36,
_ => quote.Warranty
@ -67,45 +47,32 @@ public static class QuoteHandling
quote = CalculateTotals(quote);
return quote;
}
catch (Exception e)
{
catch (Exception e) {
Console.WriteLine(e);
return new();
}
}
private static List<LineItem> ReadLineItemsFromClipboard(string clipboard)
{
private static List<LineItem> ReadLineItemsFromClipboard(string clipboard) {
//Zeilen aufteilen
IEnumerable<string> clipboardLines = clipboard.Split(Environment.NewLine.ToCharArray());
List<string[]> clipboardList = (
from clipboardLine in clipboardLines
where clipboardLine != ""
select clipboardLine.Split('\t')
).ToList();
return ParseClipboardList(clipboardList);
List<string[]> clipboardList = (from clipboardLine in clipboardLines where clipboardLine != "" select clipboardLine.Split('\t')).ToList();
List<LineItem> lineItems = ParseClipboardList(clipboardList).Result;
return lineItems;
}
private static List<LineItem> ParseClipboardList(List<string[]> lineItemStrings)
{
private static async Task<List<LineItem>> ParseClipboardList(List<string[]> lineItemStrings) {
List<LineItem> lineItems = new();
CultureInfo cultureInfoUs = new("en-US");
foreach (string[] lineItemString in lineItemStrings)
{
//Anzahl an Spalten entspricht Clipboard
if (lineItemString.Length == 19)
{
if (lineItemString.Length == 19) {
//Header ignorieren
if (lineItemString[0] == "#")
{
continue;
}
if (lineItemString[0] == "#") continue;
//Dateiinhalt in Klasse schreiben
LineItem lineItem =
new()
{
LineItem lineItem = new() {
Position = ushort.Parse(lineItemString[0]),
ProductNumber = lineItemString[1],
OptionNumber = lineItemString[2],
@ -124,28 +91,23 @@ public static class QuoteHandling
lineItems.Add(lineItem);
}
else
{
else {
Console.WriteLine("Angebot konnte nicht eingelesen werden!");
}
}
return lineItems;
}
private static byte CheckForAcademic(Account account)
{
private static byte CheckForAcademic(Account account) {
return account.AccountType?.AccountTypeCode == null ? (byte)60 : (byte)(account.AccountType.AccountTypeCode.StartsWith("N") ? 90 : 60);
}
private static decimal GetFreight(decimal net, decimal freight)
{
private static decimal GetFreight(decimal net, decimal freight) {
decimal freightNet = net * freight / 100;
return freightNet < 3000 ? freightNet : 3000;
}
private static Quote CalculateTotals(Quote quote)
{
private static Quote CalculateTotals(Quote quote) {
quote.TotalFreightOnly = GetFreight(quote.TotalNet, quote.Freight);
quote.TotalFreight = quote.TotalNet + quote.TotalFreightOnly;
quote.TotalVat = quote.TotalFreight * Convert.ToDecimal(quote.Vat) / 100;
@ -153,8 +115,7 @@ public static class QuoteHandling
return quote;
}
private static Quote ResetTotals(Quote quote)
{
private static Quote ResetTotals(Quote quote) {
quote.TotalListprice = 0;
quote.TotalNet = 0;
quote.TotalFreightOnly = 0;
@ -165,18 +126,12 @@ public static class QuoteHandling
return quote;
}
private static decimal GetTotal(Quote quote, string type)
{
private static decimal GetTotal(Quote quote, string type) {
decimal total = 0;
if (quote.LineItems == null)
{
return total;
}
if (quote.LineItems == null) return total;
foreach (LineItem lineItem in quote.LineItems)
{
switch (type)
{
switch (type) {
case "TotalListprice":
total += lineItem.ListPrice;
break;
@ -187,49 +142,32 @@ public static class QuoteHandling
total += lineItem.TotalDiscount;
break;
}
}
if ((type == "AverageDiscount") & (quote.LineItems.Count != 0))
{
total /= quote.LineItems.Count;
}
if ((type == "AverageDiscount") & (quote.LineItems.Count != 0)) total /= quote.LineItems.Count;
return total;
}
private static bool DoesContains(Quote quote, string type)
{
if (quote.LineItems == null)
{
return false;
}
private static bool DoesContains(Quote quote, string type) {
if (quote.LineItems == null) return false;
foreach (LineItem lineItem in quote.LineItems)
{
switch (type)
{
switch (type) {
case "3PP":
if (lineItem.ProductLine == "3PP")
{
Console.WriteLine(
$"Quote contains 3PP with ProductNumber {lineItem.ProductNumber}"
);
if (lineItem.ProductLine == "3PP") {
Console.WriteLine($"Quote contains 3PP with ProductNumber {lineItem.ProductNumber}");
return true;
}
break;
case "RB":
if ((lineItem.ProductLine == "RB") & (lineItem.ProductNumber != "R2005A"))
{
Console.WriteLine(
$"Quote contains RB with ProductNumber {lineItem.ProductNumber}"
);
if ((lineItem.ProductLine == "RB") & (lineItem.ProductNumber != "R2005A")) {
Console.WriteLine($"Quote contains RB with ProductNumber {lineItem.ProductNumber}");
return true;
}
break;
}
}
return false;
}

@ -5,297 +5,172 @@ using static Gremlin_BlazorServer.Data.EntityClasses.Enums;
namespace Gremlin_BlazorServer.Services;
public abstract class TexService
{
private static readonly GenericController genericController = new();
public static async Task<StringBuilder?> CreateTex(Quote quote)
{
public abstract class TexService {
public static async Task<StringBuilder?> CreateTex(Quote quote) {
StringBuilder? texStringBuilder = await CreateTexFile(quote);
if (texStringBuilder == null)
return null;
if (texStringBuilder is null) return null;
string correctedTex = await Task.Run(() => Replace(texStringBuilder.ToString()));
return new(correctedTex);
}
private static StringBuilder? CreateBriefkopf(Contact recipient, bool tex = false)
{
if (recipient.Account?.AccountName == null)
return null;
private static StringBuilder? CreateBriefkopf(Contact recipient, bool tex = false) {
if (recipient.Account?.AccountName is null) return null;
StringBuilder briefkopf = new();
if (recipient.Gender == (byte)Gender.Male)
{
briefkopf.AppendLine($"Herr {recipient.FirstName} {recipient.LastName}");
}
else
{
briefkopf.AppendLine($"Frau {recipient.FirstName} {recipient.LastName}");
}
if (recipient.Gender == (byte)Gender.Male) briefkopf.AppendLine($"Herr {recipient.FirstName} {recipient.LastName}");
else briefkopf.AppendLine($"Frau {recipient.FirstName} {recipient.LastName}");
if (tex)
briefkopf.AppendLine("\\\\");
if (tex) briefkopf.AppendLine("\\\\");
//AccountNamen mit "&" im Namen abfangen
string accountName = recipient.Account.AccountName.Replace("&", "\\&");
briefkopf.AppendLine($"{accountName}");
if (tex)
briefkopf.AppendLine("\\\\");
if (tex) briefkopf.AppendLine("\\\\");
briefkopf.AppendLine($"{recipient.Account.Street}");
if (tex)
briefkopf.AppendLine("\\\\");
if (tex) briefkopf.AppendLine("\\\\");
briefkopf.AppendLine($"{recipient.Account.Zip} {recipient.Account.City}");
if (tex)
briefkopf.AppendLine("\\\\");
if (tex) briefkopf.AppendLine("\\\\");
return briefkopf;
}
private static async Task<StringBuilder?> CreateTexFile(Quote quote)
{
if (quote.Recipient == null || quote.LineItems == null)
return null;
private static async Task<StringBuilder?> CreateTexFile(Quote quote) {
if (quote.LineItems is null) return null;
const string rand = "2"; //RUSettingModel.GetSettingValue(Properties.Settings.Default.userSettingID, "texRand");
StringBuilder texFile =
new(
"\\documentclass[a4paper,ngerman,parskip,10pt]{scrlttr2}\n"
+ "\\usepackage{lmodern}\n"
+ "\\usepackage[T1]{fontenc}\n"
+ "\\usepackage[utf8]{inputenc}\n"
+ "\\usepackage{babel}\n"
+ "\\usepackage[hidelinks]{hyperref}\n"
);
texFile.AppendLine(
$"\\usepackage[left={rand}cm, right={rand}cm, top={rand}cm, bottom={rand}cm]{{geometry}}\n"
);
texFile.AppendLine(
"\\usepackage[table]{xcolor}\n"
+ "\\usepackage[right]{{eurosym}}\n"
+ "\\usepackage[locale=DE]{{siunitx}}\n"
+ "\\usepackage{{scrlayer-scrpage}}\n"
+ "\\usepackage{{lastpage}}\n"
+ "\\usepackage{{graphicx}}\n"
+ "\\usepackage{{multirow}}\n"
+ "\\usepackage{{longtable}}\n"
+ "\\usepackage{{enumitem}}\n"
+ "\\usepackage{{fp, xstring, spreadtab, numprint}}\n"
+ "\\DeclareSIUnit{{\\sieuro}}{{\\mbox{{\\euro}}}}"
);
StringBuilder texFile = new("\\documentclass[a4paper,ngerman,parskip,10pt]{scrlttr2}\n" + "\\usepackage{lmodern}\n" + "\\usepackage[T1]{fontenc}\n" + "\\usepackage[utf8]{inputenc}\n" + "\\usepackage{babel}\n" + "\\usepackage[hidelinks]{hyperref}\n");
texFile.AppendLine($"\\usepackage[left={rand}cm, right={rand}cm, top={rand}cm, bottom={rand}cm]{{geometry}}\n");
texFile.AppendLine("\\usepackage[table]{xcolor}\n" + "\\usepackage[right]{{eurosym}}\n" + "\\usepackage[locale=DE]{{siunitx}}\n" + "\\usepackage{{scrlayer-scrpage}}\n" + "\\usepackage{{lastpage}}\n" + "\\usepackage{{graphicx}}\n" + "\\usepackage{{multirow}}\n" + "\\usepackage{{longtable}}\n" + "\\usepackage{{enumitem}}\n" + "\\usepackage{{fp, xstring, spreadtab, numprint}}\n" + "\\DeclareSIUnit{{\\sieuro}}{{\\mbox{{\\euro}}}}");
texFile.AppendLine($"\\rohead{{{quote.QuotationNumber}}}");
texFile.AppendLine(
"\\cfoot{Seite \\thepage/\\pageref{LastPage}}\n"
+ "\\sisetup{round-integer-to-decimal,round-precision=2,round-mode=places}"
+ "\n\\newcommand{\\produkttitel}[1]{\\textsc{#1}}"
+ "\n\\renewcommand{\\arraystretch}{1.2}\n\\definecolor{AgilentBlau}{HTML}{0085d5}"
+ "\n\\setlist{noitemsep}\n\\begin{document}"
+ "\n\\begin{tabular}{p{0.4\\hsize}p{0.5\\hsize}}"
+ "\n\\multirow{4}{*}{\\includegraphics[width=0.9\\hsize]{agilentLogo.png}}"
+ "\n&\\normalsize{Agilent Technologies Deutschland GmbH}\\\\"
+ "\n&\\normalsize{Life Sciences \\& Chemical Analysis}\\\\"
+ "\n&\\normalsize{Hewlett-Packard-Str. 8}\\\\"
+ "\n&\\normalsize{D-76337 Waldbronn}"
+ "\n\\end{tabular}"
+ "\n\\par\n\\begin{flushright}"
);
if (quote.IsPriceInformation)
{
texFile.AppendLine(
"\n\\colorbox{AgilentBlau}{\\textcolor{white}{\\textsc{\\Huge{Preisinformation}}}}\n\\end{flushright}\n\\begin{tabular}{p{0.4\\hsize}p{0.6\\hsize}}"
);
}
else
{
texFile.AppendLine(
"\n\\colorbox{AgilentBlau}{\\textcolor{white}{\\textsc{\\Huge{Angebot}}}}\n\\end{flushright}\n\\begin{tabular}{p{0.4\\hsize}p{0.6\\hsize}}"
);
}
texFile.AppendLine("\\cfoot{Seite \\thepage/\\pageref{LastPage}}\n" + "\\sisetup{round-integer-to-decimal,round-precision=2,round-mode=places}" + "\n\\newcommand{\\produkttitel}[1]{\\textsc{#1}}" + "\n\\renewcommand{\\arraystretch}{1.2}\n\\definecolor{AgilentBlau}{HTML}{0085d5}" + "\n\\setlist{noitemsep}\n\\begin{document}" + "\n\\begin{tabular}{p{0.4\\hsize}p{0.5\\hsize}}" + "\n\\multirow{4}{*}{\\includegraphics[width=0.9\\hsize]{agilentLogo.png}}" + "\n&\\normalsize{Agilent Technologies Deutschland GmbH}\\\\" + "\n&\\normalsize{Life Sciences \\& Chemical Analysis}\\\\" + "\n&\\normalsize{Hewlett-Packard-Str. 8}\\\\" + "\n&\\normalsize{D-76337 Waldbronn}" + "\n\\end{tabular}" + "\n\\par\n\\begin{flushright}");
texFile.AppendLine(quote.IsPriceInformation
? "\n\\colorbox{AgilentBlau}{\\textcolor{white}{\\textsc{\\Huge{Preisinformation}}}}\n\\end{flushright}\n\\begin{tabular}{p{0.4\\hsize}p{0.6\\hsize}}"
: "\n\\colorbox{AgilentBlau}{\\textcolor{white}{\\textsc{\\Huge{Angebot}}}}\n\\end{flushright}\n\\begin{tabular}{p{0.4\\hsize}p{0.6\\hsize}}");
texFile.AppendLine("\n &\n\\multirow{4}{*}{" + "\n\\begin{tabular}{|ll|}" + "\n\\hline");
texFile.AppendLine($"\\textbf{{Angebotsnummer:}}&{quote.QuotationNumber}\\\\");
texFile.Append($"Angebotdatum:&\\today\\\\\nAngebotsgültigkeit:&{quote.ValidFor} Tage\\\\");
if (quote.SalesRep != null)
{
texFile.AppendLine(
$"\\textbf{{Ansprechpartner:}}&{quote.SalesRep.FirstName} {quote.SalesRep.LastName}\\\\"
);
if (quote.SalesRep is not null) {
texFile.AppendLine($"\\textbf{{Ansprechpartner:}}&{quote.SalesRep.FirstName} {quote.SalesRep.LastName}\\\\");
texFile.AppendLine($"Telefon: &{quote.SalesRep.PhoneNumber}\\\\");
texFile.AppendLine($"Mobil:&{quote.SalesRep.MobileNumber}\\\\");
texFile.AppendLine(
$"E-Mail:&\\href{{mailto:{quote.SalesRep.EMail}}}{{{quote.SalesRep.EMail}}}\\\\"
);
texFile.AppendLine($"E-Mail:&\\href{{mailto:{quote.SalesRep.EMail}}}{{{quote.SalesRep.EMail}}}\\\\");
}
texFile.AppendLine(
"\\textbf{Auftragsannahme:}&\\href{mailto:salesservices\\_germany@agilent.com}{salesservices\\_germany@agilent.com}\\\\\n\\hline\n\\end{tabular}\n}\\\\"
);
texFile.AppendLine("\\textbf{Auftragsannahme:}&\\href{mailto:salesservices\\_germany@agilent.com}{salesservices\\_germany@agilent.com}\\\\\n\\hline\n\\end{tabular}\n}\\\\");
if (quote.Recipient is not null) {
texFile.Append(CreateBriefkopf(quote.Recipient, true));
texFile.AppendLine("&\\\\\n&\\\\\n\\end{tabular}\n\\vspace{1cm}\\par ");
//Anrede
if (quote.Recipient.Gender == (byte)Gender.Male)
{
texFile.AppendLine($"Sehr geehrter Herr {quote.Recipient.LastName},\\par ");
}
else
{
texFile.AppendLine($"Sehr geehrte Frau {quote.Recipient.LastName},\\par ");
if (quote.Recipient.Gender is (byte)Gender.Male) texFile.AppendLine($"Sehr geehrter Herr {quote.Recipient.LastName},\\par ");
else texFile.AppendLine($"Sehr geehrte Frau {quote.Recipient.LastName},\\par ");
}
//Anschreiben
texFile.AppendLine(await CreateCoverletter(quote));
//RB-Disclaimer
if (quote.QuoteContainsRb)
texFile.AppendLine(CreateRbDisclaimer(quote));
if (quote.QuoteContainsRb) texFile.AppendLine(CreateRbDisclaimer(quote));
//Tabelle
texFile.AppendLine("\\begin{center}");
texFile.AppendLine("\\begin{longtable}");
if (quote.ShowSinglePrices)
{
if (!quote.ShowDiscounts)
{
if (quote.ShowSinglePrices) {
switch (quote.ShowDiscounts) {
case false:
//mit Einzelpreisen
texFile.AppendLine("{| cp{0.71\\textwidth} cr |} \\hline");
texFile.AppendLine(
@"\textbf{\#} & \textbf{Produktbeschreibung} (Produktnummer) & \textbf{Menge} & \textbf{Preis}\\ \hline \endhead"
);
}
else if (quote.ShowDiscounts)
{
texFile.AppendLine(@"\textbf{\#} & \textbf{Produktbeschreibung} (Produktnummer) & \textbf{Menge} & \textbf{Preis}\\ \hline \endhead");
break;
case true:
//mit Einzelpreisen und Discounts
texFile.AppendLine("{| cp{0.595\\textwidth} crr |} \\hline");
texFile.AppendLine(
@"\textbf{\#} & \textbf{Produktbeschreibung} (Produktnummer) & \textbf{Menge} & \textbf{Discount} & \textbf{Preis}\\ \hline \endhead"
);
texFile.AppendLine(@"\textbf{\#} & \textbf{Produktbeschreibung} (Produktnummer) & \textbf{Menge} & \textbf{Discount} & \textbf{Preis}\\ \hline \endhead");
break;
}
}
else
{
else {
//ohne Einzelpreise
texFile.AppendLine("{| cp{0.83\\textwidth} c |} \\hline");
texFile.AppendLine(
@"\textbf{\#} & \textbf{Produktbeschreibung} (Produktnummer) & \textbf{Menge}\\ \hline \endhead"
);
texFile.AppendLine(@"\textbf{\#} & \textbf{Produktbeschreibung} (Produktnummer) & \textbf{Menge}\\ \hline \endhead");
}
foreach (LineItem lineItem in quote.LineItems)
{
string lineItemTex = string.Empty;
foreach (LineItem lineItem in quote.LineItems) {
string lineItemTex = Empty;
if (lineItem.Product is null) break;
if (lineItem.CustomDescription == null)
{
if (lineItem.Product.CustomDescription is null)
lineItemTex = $"{lineItem.Position} &\\textbf{{CustomDescription missing}} ({lineItem.ProductNumber}\\#{lineItem.OptionNumber})\\newline CustomDescription missing&{lineItem.Amount}&\\SI{{{lineItem.Total}}}{{\\sieuro}}\\\\";
}
else
{
switch (quote.ShowSinglePrices)
{
switch (quote.ShowSinglePrices) {
case true when !quote.ShowDiscounts:
//mit Einzelpreisen
lineItemTex =
lineItem.OptionNumber != ""
? $"{lineItem.Position} &\\textbf{{{lineItem.CustomDescription.Heading}}} ({lineItem.ProductNumber}\\#{lineItem.OptionNumber})\\newline {lineItem.CustomDescription.DescriptionText}&{lineItem.Amount}&\\SI{{{lineItem.Total}}}{{\\sieuro}}\\\\"
: $"{lineItem.Position} &\\textbf{{{lineItem.CustomDescription.Heading}}} ({lineItem.ProductNumber})\\newline {lineItem.CustomDescription.DescriptionText}&{lineItem.Amount}&\\SI{{{lineItem.Total}}}{{\\sieuro}}\\\\";
lineItemTex = lineItem.OptionNumber != "" ? $"{lineItem.Position} &\\textbf{{{lineItem.Product.CustomDescription.Heading}}} ({lineItem.ProductNumber}\\#{lineItem.OptionNumber})\\newline {lineItem.Product.CustomDescription.DescriptionText}&{lineItem.Amount}&\\SI{{{lineItem.Total}}}{{\\sieuro}}\\\\" : $"{lineItem.Position} &\\textbf{{{lineItem.Product.CustomDescription.Heading}}} ({lineItem.ProductNumber})\\newline {lineItem.Product.CustomDescription.DescriptionText}&{lineItem.Amount}&\\SI{{{lineItem.Total}}}{{\\sieuro}}\\\\";
break;
case true:
{
case true: {
if (quote.ShowDiscounts)
{
//mit Einzelpreisen und Discounts
lineItemTex =
lineItem.OptionNumber != ""
? $"{lineItem.Position} &\\textbf{{{lineItem.CustomDescription.Heading}}} ({lineItem.ProductNumber}\\#{lineItem.OptionNumber})\\newline {lineItem.CustomDescription.DescriptionText}\\newline Listenpreis: \\SI{{{lineItem.ListPrice}}}{{\\sieuro}}&{lineItem.Amount}&\\SI{{{lineItem.TotalDiscount}}}{{\\%}}&\\SI{{{lineItem.Total}}}{{\\sieuro}}\\\\"
: $"{lineItem.Position} &\\textbf{{{lineItem.CustomDescription.Heading}}} ({lineItem.ProductNumber})\\newline {lineItem.CustomDescription.DescriptionText}\\newline Listenpreis: \\SI{{{lineItem.ListPrice}}}{{\\sieuro}}&{lineItem.Amount}&\\SI{{{lineItem.TotalDiscount}}}{{\\%}}&\\SI{{{lineItem.Total}}}{{\\sieuro}}\\\\";
}
lineItemTex = lineItem.OptionNumber != "" ? $"{lineItem.Position} &\\textbf{{{lineItem.Product.CustomDescription.Heading}}} ({lineItem.ProductNumber}\\#{lineItem.OptionNumber})\\newline {lineItem.Product.CustomDescription.DescriptionText}\\newline Listenpreis: \\SI{{{lineItem.ListPrice}}}{{\\sieuro}}&{lineItem.Amount}&\\SI{{{lineItem.TotalDiscount}}}{{\\%}}&\\SI{{{lineItem.Total}}}{{\\sieuro}}\\\\" : $"{lineItem.Position} &\\textbf{{{lineItem.Product.CustomDescription.Heading}}} ({lineItem.ProductNumber})\\newline {lineItem.Product.CustomDescription.DescriptionText}\\newline Listenpreis: \\SI{{{lineItem.ListPrice}}}{{\\sieuro}}&{lineItem.Amount}&\\SI{{{lineItem.TotalDiscount}}}{{\\%}}&\\SI{{{lineItem.Total}}}{{\\sieuro}}\\\\";
break;
}
case false:
//ohne Einzelpreise
lineItemTex =
lineItem.OptionNumber != ""
? $"{lineItem.Position} &\\textbf{{{lineItem.CustomDescription.Heading}}} ({lineItem.ProductNumber}\\#{lineItem.OptionNumber})\\newline {lineItem.CustomDescription.DescriptionText}&{lineItem.Amount}\\\\"
: $"{lineItem.Position} &\\textbf{{{lineItem.CustomDescription.Heading}}} ({lineItem.ProductNumber})\\newline {lineItem.CustomDescription.DescriptionText}&{lineItem.Amount}\\\\";
lineItemTex = lineItem.OptionNumber != "" ? $"{lineItem.Position} &\\textbf{{{lineItem.Product.CustomDescription.Heading}}} ({lineItem.ProductNumber}\\#{lineItem.OptionNumber})\\newline {lineItem.Product.CustomDescription.DescriptionText}&{lineItem.Amount}\\\\" : $"{lineItem.Position} &\\textbf{{{lineItem.Product.CustomDescription.Heading}}} ({lineItem.ProductNumber})\\newline {lineItem.Product.CustomDescription.DescriptionText}&{lineItem.Amount}\\\\";
break;
}
}
texFile.Append(lineItemTex + "\n");
}
texFile.AppendLine("\\hline\n" + "\\end{longtable}\n" + "\\end{center}\n");
texFile.AppendLine(
"\\vspace{-2cm}\n" + "\\begin{flushright}\n\n" + "\\begin{tabular}{|rr|}\n" + "\\hline"
);
texFile.AppendLine("\\vspace{-2cm}\n" + "\\begin{flushright}\n\n" + "\\begin{tabular}{|rr|}\n" + "\\hline");
//Summe netto
texFile.AppendLine($"\\textbf{{Summe netto}} & \\SI{{{quote.TotalNet}}}{{\\sieuro}}\\\\");
//Frachtkosten
texFile.AppendLine(
$"\\textbf{{Versand und Bereitstellungskosten ({quote.Freight}\\%)}} & \\SI{{{quote.TotalFreightOnly}}}{{\\sieuro}}\\\\"
);
texFile.AppendLine($"\\textbf{{Versand und Bereitstellungskosten ({quote.Freight}\\%)}} & \\SI{{{quote.TotalFreightOnly}}}{{\\sieuro}}\\\\");
//Gesamtsumme netto
texFile.AppendLine(
$"\\textbf{{Gesamtsumme netto}} & \\SI{{{quote.TotalFreight}}}{{\\sieuro}}\\\\"
);
texFile.AppendLine($"\\textbf{{Gesamtsumme netto}} & \\SI{{{quote.TotalFreight}}}{{\\sieuro}}\\\\");
//mit Mehrwertsteuer
if (quote.ShowBrutto)
{
texFile.AppendLine(
$"\\textbf{{Umsatzsteuer ({quote.Vat}\\%)}} & \\SI{{{quote.TotalVat}}}{{\\sieuro}}\\\\"
);
texFile.AppendLine(
$"\\textbf{{Gesamtsumme brutto}} & \\SI{{{quote.TotalGross}}}{{\\sieuro}}\\\\"
);
if (quote.ShowBrutto) {
texFile.AppendLine($"\\textbf{{Umsatzsteuer ({quote.Vat}\\%)}} & \\SI{{{quote.TotalVat}}}{{\\sieuro}}\\\\");
texFile.AppendLine($"\\textbf{{Gesamtsumme brutto}} & \\SI{{{quote.TotalGross}}}{{\\sieuro}}\\\\");
}
texFile.Append(
"\\hline\n\\end{tabular}\n\n\\end{flushright}\n\nDer Betrag versteht sich zzgl. der gesetzlichen Steuern.\\\\\nDiese werden im Rechnungszeitraum auf der Rechnung gesondert ausgewiesen.\\\\\nZahlungsbedingungen: 30 Tage netto ab Rechnungsdatum.\\\\\nIncoterm (2010) für Lieferungen innerhalb Deutschlands: DDP.\n\\begin{small}\n\n"
);
texFile.AppendLine(
$"\\textbf{{Gewährleistung:}}\\\\\nDie Gewährleistung für Zubehör und Ersatzteilprodukte und für Analytik-Hardwareprodukte beträgt {quote.Warranty} Monate.\n"
);
texFile.Append("\\hline\n\\end{tabular}\n\n\\end{flushright}\n\nDer Betrag versteht sich zzgl. der gesetzlichen Steuern.\\\\\nDiese werden im Rechnungszeitraum auf der Rechnung gesondert ausgewiesen.\\\\\nZahlungsbedingungen: 30 Tage netto ab Rechnungsdatum.\\\\\nIncoterm (2010) für Lieferungen innerhalb Deutschlands: DDP.\n\\begin{small}\n\n");
texFile.AppendLine($"\\textbf{{Gewährleistung:}}\\\\\nDie Gewährleistung für Zubehör und Ersatzteilprodukte und für Analytik-Hardwareprodukte beträgt {quote.Warranty} Monate.\n");
//3PP-Disclaimer
if (quote.QuoteContains3Pp)
texFile.AppendLine(Create3PpDisclaimer(quote));
texFile.AppendLine(
"\\textbf{Hinweis:}\\\\ \n"
+ "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.\n"
+ "\\end{small}\n \n"
+ "\\begin{scriptsize}\n"
+ "Agilent Technologies Deutschland GmbH, Hewlett-Packard-Str. 8, D-76337 Waldbronn\\\\\nTelefon +49 (0)7243-602-0\\\\\nUSt.-IdNr.: DE812729296, WEEE-Reg.-Nr. DE 86631749\\\\\nSitz der Gesellschaft: Waldbronn Amtsgericht Mannheim, HRB 723782\\\\\nGeschäftsführer: Dr. Andreas Kistner (Vorsitzender der Geschäftsführung), Armin Jehle, Norbert Sabatzki, Dr. Knut Wintergerst\\\\\n"
+ "\\href{www.agilent.com}{www.agilent.com}\n\\end{scriptsize}\n\\end{document}"
);
texFile.AppendLine("\\textbf{Hinweis:}\\\\ \n" + "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.\n" + "\\end{small}\n \n" + "\\begin{scriptsize}\n" + "Agilent Technologies Deutschland GmbH, Hewlett-Packard-Str. 8, D-76337 Waldbronn\\\\\nTelefon +49 (0)7243-602-0\\\\\nUSt.-IdNr.: DE812729296, WEEE-Reg.-Nr. DE 86631749\\\\\nSitz der Gesellschaft: Waldbronn Amtsgericht Mannheim, HRB 723782\\\\\nGeschäftsführer: Dr. Andreas Kistner (Vorsitzender der Geschäftsführung), Armin Jehle, Norbert Sabatzki, Dr. Knut Wintergerst\\\\\n" + "\\href{www.agilent.com}{www.agilent.com}\n\\end{scriptsize}\n\\end{document}");
return texFile;
}
private static string CreateRbDisclaimer(Quote quote)
{
private static string CreateRbDisclaimer(Quote quote) {
if (quote.LineItems == null)
return Empty;
string rbDisclaimer =
"\\textbf{Wichtiger Hinweis zur Bestellung von überholten Geräten}\\\\\n";
rbDisclaimer +=
"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:\n";
string rbDisclaimer = "\\textbf{Wichtiger Hinweis zur Bestellung von überholten Geräten}\\\\\n";
rbDisclaimer += "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:\n";
// List<LineItem> lineItemsWithRb = quote.LineItems.Where(lI => lI.ProductLine == "RB").ToList();
// rbDisclaimer += "\\begin{center}\n\\begin{tabular}{clc}\n";
@ -313,36 +188,23 @@ public abstract class TexService
return rbDisclaimer;
}
private static string Create3PpDisclaimer(Quote quote)
{
private static string Create3PpDisclaimer(Quote quote) {
if (quote.LineItems == null)
return Empty;
string dreipp =
"\\textbf{Hinweis zu Non-Agilent-Produkten}\\\\ \n"
+ "Bitte beachten Sie, dass das/die o.g. Produkt/e ";
string dreipp = "\\textbf{Hinweis zu Non-Agilent-Produkten}\\\\ \n" + "Bitte beachten Sie, dass das/die o.g. Produkt/e ";
//List all 3PP product numbers
List<LineItem> lineItemsWith3Pp = quote.LineItems
.Where(lI => lI.ProductLine == "3PP")
.ToList();
List<LineItem> lineItemsWith3Pp = quote.LineItems.Where(lI => lI.ProductLine == "3PP").ToList();
for (int i = 0; i < lineItemsWith3Pp.Count; i++)
{
if (i < lineItemsWith3Pp.Count - 1)
{
dreipp += $"{lineItemsWith3Pp[i].ProductNumber}, ";
}
else
{
dreipp += $"{lineItemsWith3Pp[i].ProductNumber}";
}
}
//Get all 3PP Supplier
//List<Supllier> supllier3PP = lineItemWith3PP.ProductLine.Supplier;
dreipp +=
" nicht von Agilent Technologies hergestellt wird/werden. Agilent Technologies lehnt daher jede Art der Haftung für Leistung, Qualität, Zuverlässigkeitund Lieferung für dieses/r Produkt/e ab.\\\\\n"
+ "Die Standardgewährleistung, einschließlich Schadensersatz für die Rechtsverletzung von intellektuellem Eigentum, liegt beim Hersteller bzw. Lieferanten des/r Produkt/e, solange nichts anders im Angebot von Agilent Technologies spezifiziert wird.\n";
dreipp += " nicht von Agilent Technologies hergestellt wird/werden. Agilent Technologies lehnt daher jede Art der Haftung für Leistung, Qualität, Zuverlässigkeitund Lieferung für dieses/r Produkt/e ab.\\\\\n" + "Die Standardgewährleistung, einschließlich Schadensersatz für die Rechtsverletzung von intellektuellem Eigentum, liegt beim Hersteller bzw. Lieferanten des/r Produkt/e, solange nichts anders im Angebot von Agilent Technologies spezifiziert wird.\n";
//dreipp += "\\textbf{Hersteller:}";
//supllier3PP
@ -350,70 +212,55 @@ public abstract class TexService
return dreipp;
}
private static async Task<string> GetCoverletterRow(LineItem lineItem)
{
if (lineItem.CustomDescription == null) return $"\\item CustomDescription missing (\\#{lineItem.Position})\n";
return lineItem.CustomDescription.CoverletterText == ""
? lineItem.CustomDescription == null
private static string GetCoverletterRow(LineItem lineItem) {
if (lineItem.Product is null) return $"\\item Product missing (\\#{lineItem.Position})\n";
return lineItem.Product.CustomDescription is null
? $"\\item CustomDescription missing (\\#{lineItem.Position})\n"
: lineItem.Product.CustomDescription.CoverletterText is ""
? lineItem.Product.CustomDescription is null
? Empty
: $"\\item {lineItem.CustomDescription.Heading} (\\#{lineItem.Position})\n"
: lineItem.CustomDescription == null
: $"\\item {lineItem.Product.CustomDescription.Heading} (\\#{lineItem.Position})\n"
: lineItem.Product.CustomDescription is null
? Empty
: $"\\item {lineItem.CustomDescription.CoverletterText} (\\#{lineItem.Position})\n";
: $"\\item {lineItem.Product.CustomDescription.CoverletterText} (\\#{lineItem.Position})\n";
}
private static async Task<string> CreateCoverletter(Quote quote)
{
private static async Task<string> CreateCoverletter(Quote quote) {
bool subitem = false;
string coverLetter =
$"nachfolgend erhalten Sie Ihr gewünschtes Angebot über ein(e) {quote.Description}.\\\\\n"
+ "Es umfasst im Einzelnen:\n"
+ "\\begin{itemize}\n";
string coverLetter = $"nachfolgend erhalten Sie Ihr gewünschtes Angebot über ein(e) {quote.Description}.\\\\\n" + "Es umfasst im Einzelnen:\n" + "\\begin{itemize}\n";
if (quote.LineItems == null)
return Empty;
if (quote.LineItems is null) return Empty;
foreach (LineItem lineItem in quote.LineItems)
{
if (lineItem.OptionNumber == "")
{
foreach (LineItem lineItem in quote.LineItems) {
if (lineItem.OptionNumber is "") {
//Hauptitem
if (subitem)
{
if (subitem) {
//vorheriges Subitem schließen
coverLetter += "\\end{itemize}\n";
subitem = false;
}
}
else
{
if (!subitem)
{
else {
if (!subitem) {
//neues Subitem
subitem = true;
coverLetter += "\\begin{itemize}\n";
}
}
coverLetter += await GetCoverletterRow(lineItem);
coverLetter += GetCoverletterRow(lineItem);
}
if (subitem)
//wenn das letzte Item ein Subitem war
coverLetter += "\\end{itemize}\n";
coverLetter +=
"\\end{itemize}\n"
+ "Für Rückfragen und Änderungswünsche stehe ich Ihnen gerne zur Verfügung.\\par\n"
+ "Mit freundlichen Grüßen\\\\\n"
+ "\\includegraphics[width = 5cm]{signWoitschetzki.png}\n"
+ "\\vspace{1cm} \\\\ \n";
coverLetter += "\\end{itemize}\n" + "Für Rückfragen und Änderungswünsche stehe ich Ihnen gerne zur Verfügung.\\par\n" + "Mit freundlichen Grüßen\\\\\n" + "\\includegraphics[width = 5cm]{signWoitschetzki.png}\n" + "\\vspace{1cm} \\\\ \n";
return coverLetter;
}
private static string Replace(string text)
{
private static string Replace(string text) {
if (text == "")
return text;

@ -0,0 +1,22 @@
# 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 G7111B 29 1260 Infinity II quaternaere Pumpe 1 25079 0 0 45 13793.45 13793.45 25 20 0 0 ISL100P1 Pumps
2 G7111B 001 29 HPLC System Tool Kit 1260 Infinity II 1 400 0 0 45 220 220 25 20 0 0
3 G7111B 030 29 Aktive Kolbenhinterspuelung 1 1463 0 0 45 804.65 804.65 25 20 0 0
4 G7111B 032 29 Aktiveinlassventil (AIV) 1 889 0 0 45 488.95 488.95 25 20 0 0
5 G7111B 094 29 Poroshell 120 EC-C18 3,0x150mm, 2,7um 1 1 0 0 45 0.55 0.55 25 20 0 0
6 G7129A 29 1260 Inf. II Fluessigprobengeber 1 19905 0 0 45 10947.75 10947.75 25 20 0 0 ISL100A1 Autosamplers
7 G7129A 010 29 Standard-Schublade (6x11 Probenflaschen) 1 375 0 0 45 206.25 206.25 25 20 0 0
8 G7129A 060 29 Nutzung vorhandene Lizenz 1 -1793 0 0 45 -986.15 -986.15 25 20 0 0
9 G7116A 29 1260 Infinity II Therm. f. mehr. Saeulen 1 6494 0 0 45 3571.7 3571.7 25 20 0 0 ISL100LC1 LC Hardware
10 G7116A 058 29 Ventilantrieb fuer 1260 Infinity II MCT 1 1541 0 0 45 847.55 847.55 25 20 0 0
11 G4237A 29 4Pos./10Anschl., 4-Saeulenausw. 800 bar 1 4808 0 0 45 2644.4 2644.4 25 20 0 0 ISL100LCV LC Valves
12 G4237A 006 29 Kapillarkit 0,17 mm, 4-Saeulen, m. QC-HE 1 3474 0 0 45 1910.7 1910.7 25 20 0 0
13 G7117C 29 1260 Infinity II Diodenarray-Detektor HS 1 24906 0 0 45 13698.3 13698.3 25 20 0 0 ISL100D1 Detectors
14 G7121B 29 1260 Infinity II FLD Spektren 1 21984 0 0 45 12091.2 12091.2 25 20 0 0 ISL100D1 Detectors
15 M8431AA LI OpenLab CDS Geraeteverbindung 1 1364 0 0 45 750.2 750.2 25 20 0 0 ISF300F100 OpenLAB CDS Software
16 M8431AA 001 LI LC-Geraeteverbindung 1 0 0 0 45 0 0 25 20 0 0
17 M8431AA 005 LI 3D UV/DAD-Verb. 1 0 0 0 45 0 0 25 20 0 0
18 SYS-LC-1260IIE 74 LC 1260 Infinity II System m. Zusatzfkt. 1 0 0 0 20 0 0 20 0 0 0 TSSYS0SYLC Service Systems - Liquid Chromatography
19 SYS-LC-1260IIE 2A9 74 Standard-Einweisung 1 1193 0 0 20 954.4 954.4 20 0 0 0 TSSTRN Training Services
20 SYS-LC-1260IIE 9EC 74 Erweit. Gewaehr. fuer Akad. - 2J, kompl. 1 5215 0 0 40 3129 3129 40 0 0 0 TSSYSX Academic Extended Warranty
21 R2005A RB Eingetauschte Geraete Deinst. und Vers. 1 0 0 0 0 0 0 0 0 0 0
1 # 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
2 1 G7111B 29 1260 Infinity II quaternaere Pumpe 1 25079 0 0 45 13793.45 13793.45 25 20 0 0 ISL100P1 Pumps
3 2 G7111B 001 29 HPLC System Tool Kit 1260 Infinity II 1 400 0 0 45 220 220 25 20 0 0
4 3 G7111B 030 29 Aktive Kolbenhinterspuelung 1 1463 0 0 45 804.65 804.65 25 20 0 0
5 4 G7111B 032 29 Aktiveinlassventil (AIV) 1 889 0 0 45 488.95 488.95 25 20 0 0
6 5 G7111B 094 29 Poroshell 120 EC-C18 3,0x150mm, 2,7um 1 1 0 0 45 0.55 0.55 25 20 0 0
7 6 G7129A 29 1260 Inf. II Fluessigprobengeber 1 19905 0 0 45 10947.75 10947.75 25 20 0 0 ISL100A1 Autosamplers
8 7 G7129A 010 29 Standard-Schublade (6x11 Probenflaschen) 1 375 0 0 45 206.25 206.25 25 20 0 0
9 8 G7129A 060 29 Nutzung vorhandene Lizenz 1 -1793 0 0 45 -986.15 -986.15 25 20 0 0
10 9 G7116A 29 1260 Infinity II Therm. f. mehr. Saeulen 1 6494 0 0 45 3571.7 3571.7 25 20 0 0 ISL100LC1 LC Hardware
11 10 G7116A 058 29 Ventilantrieb fuer 1260 Infinity II MCT 1 1541 0 0 45 847.55 847.55 25 20 0 0
12 11 G4237A 29 4Pos./10Anschl., 4-Saeulenausw. 800 bar 1 4808 0 0 45 2644.4 2644.4 25 20 0 0 ISL100LCV LC Valves
13 12 G4237A 006 29 Kapillarkit 0,17 mm, 4-Saeulen, m. QC-HE 1 3474 0 0 45 1910.7 1910.7 25 20 0 0
14 13 G7117C 29 1260 Infinity II Diodenarray-Detektor HS 1 24906 0 0 45 13698.3 13698.3 25 20 0 0 ISL100D1 Detectors
15 14 G7121B 29 1260 Infinity II FLD Spektren 1 21984 0 0 45 12091.2 12091.2 25 20 0 0 ISL100D1 Detectors
16 15 M8431AA LI OpenLab CDS Geraeteverbindung 1 1364 0 0 45 750.2 750.2 25 20 0 0 ISF300F100 OpenLAB CDS Software
17 16 M8431AA 001 LI LC-Geraeteverbindung 1 0 0 0 45 0 0 25 20 0 0
18 17 M8431AA 005 LI 3D UV/DAD-Verb. 1 0 0 0 45 0 0 25 20 0 0
19 18 SYS-LC-1260IIE 74 LC 1260 Infinity II System m. Zusatzfkt. 1 0 0 0 20 0 0 20 0 0 0 TSSYS0SYLC Service Systems - Liquid Chromatography
20 19 SYS-LC-1260IIE 2A9 74 Standard-Einweisung 1 1193 0 0 20 954.4 954.4 20 0 0 0 TSSTRN Training Services
21 20 SYS-LC-1260IIE 9EC 74 Erweit. Gewaehr. fuer Akad. - 2J, kompl. 1 5215 0 0 40 3129 3129 40 0 0 0 TSSYSX Academic Extended Warranty
22 21 R2005A RB Eingetauschte Geraete Deinst. und Vers. 1 0 0 0 0 0 0 0 0 0 0

@ -0,0 +1,177 @@
\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-423-223}
\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{Preisinformation}}}}
\end{flushright}
\begin{tabular}{p{0.4\hsize}p{0.6\hsize}}
&
\multirow{4}{*}{
\begin{tabular}{|ll|}
\hline
\textbf{Angebotsnummer:}&DE-83PE89-423-223\\
Angebotdatum:&\today\\
Angebotsgültigkeit:&60 Tage\\\textbf{Ansprechpartner:}&Sascha Woitschetzki\\
Telefon: &+49 208 74129134\\
Mobil:&+49 176 22285334\\
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 Kristina Witzler
\\
Institut für Arbeitsschutz der Deutschen Gesetzlic
\\
Alte Heerstr. 111
\\
53757 Sankt augustin
\\
&\\
&\\
\end{tabular}
\vspace{1cm}\par
Sehr geehrte Frau Witzler,\par
nachfolgend erhalten Sie Ihr gewünschtes Angebot über ein(e) Gerät.\\
Es umfasst im Einzelnen:
\begin{itemize}
\item quaternäre Pumpe mit integriertem Entgaser (\#1)
\begin{itemize}
\item Werkzeugsatz (\#2)
\item Aktive Kolbenhinterspülung (\#3)
\item Aktives Einlassventil (\#4)
\item Säule (\#5)
\end{itemize}
\item Vialsampler (\#6)
\begin{itemize}
\item Probenteller für 6x11 2,0 ml Vials (\#7)
\item Ohne Gerätetreiber (\#8)
\end{itemize}
\item Säulenthermostat (\#9)
\begin{itemize}
\item Ventilantrieb (\#10)
\end{itemize}
\item 4-Säulenauswahlventil (\#11)
\begin{itemize}
\item Kapillarkit (\#12)
\end{itemize}
\item Diodenarraydetektor High Sensitivity (\#13)
\item Fluoreszenzspektrendetektor (\#14)
\item OpenLab CDS 2 Instrument Connection (\#15)
\begin{itemize}
\item OpenLab CDS 2 IC für LC (\#16)
\item OpenLab CDS 2 IC für 3D-UV/DAD (\#17)
\end{itemize}
\item 1260 Infinity II HPLC mit Zusatzfunktionen (\#18)
\begin{itemize}
\item Einführung (\#19)
\item Zwei Jahre Gewährleistung (\#20)
\end{itemize}
\item Überprüfung, Deinstallation und Versand (\#21)
\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{Quaternäre Pumpe} (G7111B)\newline 1260 Infinity II quaternäre Pumpe, Maximaldruck 600 bar. Mit integriertem 4-Kanal-Entgaser, vergünstigter Säule, Verbindungskapillaren, Lösemittelwanne und -flaschen.\newline Listenpreis: \SI{25079}{\sieuro}&1&\SI{45}{\%}&\SI{13793.45}{\sieuro}\\
2 &\textbf{Werkzeugsatz} (G7111B\#001)\newline HPLC System Tool Kit, für Agilent 1260/1290 Infinity II LC.\newline Listenpreis: \SI{400}{\sieuro}&1&\SI{45}{\%}&\SI{220}{\sieuro}\\
3 &\textbf{Aktive Kolbenhinterspülung} (G7111B\#030)\newline Automatische Reinigung und Pflege der Pumpenköpfe, -dichtungen und -ventile für maximale Lebensdauer. Besonders empfohlen bei salzhaltigen Analyten oder Puffern.\newline Listenpreis: \SI{1463}{\sieuro}&1&\SI{45}{\%}&\SI{804.65}{\sieuro}\\
4 &\textbf{Aktives Einlassventil} (G7111B\#032)\newline Aktives Einlassventil (AIV) für einen zuverlässigen Pumpenbetrieb bei der Verwendung von Puffern.\newline Listenpreis: \SI{889}{\sieuro}&1&\SI{45}{\%}&\SI{488.95}{\sieuro}\\
5 &\textbf{Säule} (G7111B\#094)\newline InfinityLab Poroshell 120 EC-C18, 3.0 x 150 mm, 2.7 µm.\newline Listenpreis: \SI{1}{\sieuro}&1&\SI{45}{\%}&\SI{0.55}{\sieuro}\\
6 &\textbf{Vialsampler} (G7129A)\newline 1260 Infinity II automatischer Flüssigprobengeber zur Verwendung bei bis zu 600 bar. Mit integriertem Nadelspülanschluss zur Minimierung der Verschleppung, 100 µl Dosiereinheit und 100 µl Probenschleife. Inklusive Gerätetreiber für ein LC-System (2D-UV).\newline Listenpreis: \SI{19905}{\sieuro}&1&\SI{45}{\%}&\SI{10947.75}{\sieuro}\\
7 &\textbf{Probenteller für 6x11 2,0 ml Vials} (G7129A\#010)\newline \newline Listenpreis: \SI{375}{\sieuro}&1&\SI{45}{\%}&\SI{206.25}{\sieuro}\\
8 &\textbf{Ohne Gerätetreiber} (G7129A\#060)\newline Es wird ein vorhandener Gerätetreiber verwendet oder mit der Software angeboten.\newline Listenpreis: \SI{-1793}{\sieuro}&1&\SI{45}{\%}&\SI{-986.15}{\sieuro}\\
9 &\textbf{Säulenthermostat} (G7116A)\newline 1260 Infinity II Thermostat für bis zu vier 30 cm Säulen, Temperaturbereich: 10° unter Raumtemperatur (min. 4 °C) bis max. 85 °C, inkl. Säulenidentifikations-Kit. Ventilantrieb optional.\newline Listenpreis: \SI{6494}{\sieuro}&1&\SI{45}{\%}&\SI{3571.7}{\sieuro}\\
10 &\textbf{Ventilantrieb} (G7116A\#058)\newline Ventilantrieb für 1260 Infinity II Thermostat G7116A. Zur Verwendung mit QuickChange-Ventilköpfen.\newline Listenpreis: \SI{1541}{\sieuro}&1&\SI{45}{\%}&\SI{847.55}{\sieuro}\\
11 &\textbf{4-Säulenauswahlventil} (G4237A)\newline QuickChange-Ventilkopf zur Auswahl von 4 Säulen (4Pos./10 Anschlüsse), max. 800 bar. Zum schnellen Säulenwechsel oder Schaltung eines Bypasses zur Direktaufgabe auf das Massenspektrometer.\newline Listenpreis: \SI{4808}{\sieuro}&1&\SI{45}{\%}&\SI{2644.4}{\sieuro}\\
12 &\textbf{Kapillarkit} (G4237A\#006)\newline 4-Säulenauswahlventil-Kapillarkit, Inhalt: 0,17 mm ID Kapillaren und vier Quick Connect-Wärmetauscher, zur Verwendung in G7116A.\newline Listenpreis: \SI{3474}{\sieuro}&1&\SI{45}{\%}&\SI{1910.7}{\sieuro}\\
13 &\textbf{Diodenarraydetektor HS} (G7117C)\newline 1260 Infinity II Diodenarray-Detektor high sensitivity für höchste Empfindlichkeit, 120 Hz Datenrate für schnelle Multiwellenlängen- und Spektralanalysen. Messbereich 190 640 nm, RFID-Tags für Zelle und Lampe. Inklusive Standard-Max-Light-Flusszelle (10 mm, V = 1 µl, max. 70 bar).\newline Listenpreis: \SI{24906}{\sieuro}&1&\SI{45}{\%}&\SI{13698.3}{\sieuro}\\
14 &\textbf{Fluoreszenzspektrendetektor} (G7121B)\newline 1260 Infinity II Fluoreszenzdetektor, spektrenfähig.\newline Für Multiwellenlängen-Detektion, Online-Aufnahme von  Anregungs- und Emissionsspektren (200 1200 nm), Datenrate bis 148 Hz. Inkl. Standard-Durchflusszelle (V = 8 µl, max. 20 bar).\newline Listenpreis: \SI{21984}{\sieuro}&1&\SI{45}{\%}&\SI{12091.2}{\sieuro}\\
15 &\textbf{OpenLab CDS 2 Instrument Connection} (M8431AA)\newline \newline Listenpreis: \SI{1364}{\sieuro}&1&\SI{45}{\%}&\SI{750.2}{\sieuro}\\
16 &\textbf{OpenLab CDS 2 IC für LC} (M8431AA\#001)\newline Lizenz und Treiber zur Gerätesteuerung unter OpenLab CDS. Gerätetyp: LC (ohne DAD)\newline Listenpreis: \SI{0}{\sieuro}&1&\SI{45}{\%}&\SI{0}{\sieuro}\\
17 &\textbf{OpenLab CDS 2 IC für 3D-UV/DAD} (M8431AA\#005)\newline Lizenz und Treiber zur Gerätesteuerung unter OpenLab CDS. Gerätetyp: 3D-UV/DAD\newline Listenpreis: \SI{0}{\sieuro}&1&\SI{45}{\%}&\SI{0}{\sieuro}\\
18 &\textbf{1260 Infinity II HPLC mit Zusatzfunktionen} (SYS-LC-1260IIE)\newline \newline Listenpreis: \SI{0}{\sieuro}&1&\SI{20}{\%}&\SI{0}{\sieuro}\\
19 &\textbf{Einführung} (SYS-LC-1260IIE\#2A9)\newline Standardeinweisung für neue Anwender im Rahmen der Installation.\newline Listenpreis: \SI{1193}{\sieuro}&1&\SI{20}{\%}&\SI{954.4}{\sieuro}\\
20 &\textbf{Erweiterte Gewährleistung für akademische Kunden, zwei Jahre komplett} (SYS-LC-1260IIE\#9EC)\newline Verlängerung der Gewährleistung von 12 auf 24 Monate.\newline Listenpreis: \SI{5215}{\sieuro}&1&\SI{40}{\%}&\SI{3129}{\sieuro}\\
21 &\textbf{Überprüfung, Deinstallation und Versand} (R2005A)\newline Überprüfung, Deinstallation und Versand der in Zahlung gegebenen Geräte.\newline Die erfolgreiche Überprüfung der Geräte durch einen Agilent Techniker ist Voraussetzung für die Annahme der Inzahlungnahme durch Agilent.\newline Listenpreis: \SI{0}{\sieuro}&1&\SI{0}{\%}&\SI{0}{\sieuro}\\
\hline
\end{longtable}
\end{center}
\vspace{-2cm}
\begin{flushright}
\begin{tabular}{|rr|}
\hline
\textbf{Summe netto} & \SI{65072.90}{\sieuro}\\
\textbf{Versand und Bereitstellungskosten (3\%)} & \SI{1952.187}{\sieuro}\\
\textbf{Gesamtsumme netto} & \SI{67025.087}{\sieuro}\\
\textbf{Umsatzsteuer (19\%)} & \SI{12734.76653}{\sieuro}\\
\textbf{Gesamtsumme brutto} & \SI{79759.85353}{\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 24 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}

@ -0,0 +1,22 @@
# 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 G7111B 29 1260 Infinity II quaternaere Pumpe 1 25079 0 0 45 13793.45 13793.45 25 20 0 0 ISL100P1 Pumps
2 G7111B 001 29 HPLC System Tool Kit 1260 Infinity II 1 400 0 0 45 220 220 25 20 0 0
3 G7111B 030 29 Aktive Kolbenhinterspuelung 1 1463 0 0 45 804.65 804.65 25 20 0 0
4 G7111B 032 29 Aktiveinlassventil (AIV) 1 889 0 0 45 488.95 488.95 25 20 0 0
5 G7111B 094 29 Poroshell 120 EC-C18 3,0x150mm, 2,7um 1 1 0 0 45 0.55 0.55 25 20 0 0
6 G7129A 29 1260 Inf. II Fluessigprobengeber 1 19905 0 0 45 10947.75 10947.75 25 20 0 0 ISL100A1 Autosamplers
7 G7129A 010 29 Standard-Schublade (6x11 Probenflaschen) 1 375 0 0 45 206.25 206.25 25 20 0 0
8 G7129A 060 29 Nutzung vorhandene Lizenz 1 -1793 0 0 45 -986.15 -986.15 25 20 0 0
9 G7116A 29 1260 Infinity II Therm. f. mehr. Saeulen 1 6494 0 0 45 3571.7 3571.7 25 20 0 0 ISL100LC1 LC Hardware
10 G7116A 058 29 Ventilantrieb fuer 1260 Infinity II MCT 1 1541 0 0 45 847.55 847.55 25 20 0 0
11 G4237A 29 4Pos./10Anschl., 4-Saeulenausw. 800 bar 1 4808 0 0 45 2644.4 2644.4 25 20 0 0 ISL100LCV LC Valves
12 G4237A 006 29 Kapillarkit 0,17 mm, 4-Saeulen, m. QC-HE 1 3474 0 0 45 1910.7 1910.7 25 20 0 0
13 G7117C 29 1260 Infinity II Diodenarray-Detektor HS 1 24906 0 0 45 13698.3 13698.3 25 20 0 0 ISL100D1 Detectors
14 G7121B 29 1260 Infinity II FLD Spektren 1 21984 0 0 45 12091.2 12091.2 25 20 0 0 ISL100D1 Detectors
15 M8431AA LI OpenLab CDS Geraeteverbindung 1 1364 0 0 45 750.2 750.2 25 20 0 0 ISF300F100 OpenLAB CDS Software
16 M8431AA 001 LI LC-Geraeteverbindung 1 0 0 0 45 0 0 25 20 0 0
17 M8431AA 005 LI 3D UV/DAD-Verb. 1 0 0 0 45 0 0 25 20 0 0
18 SYS-LC-1260IIE 74 LC 1260 Infinity II System m. Zusatzfkt. 1 0 0 0 20 0 0 20 0 0 0 TSSYS0SYLC Service Systems - Liquid Chromatography
19 SYS-LC-1260IIE 2A9 74 Standard-Einweisung 1 1193 0 0 20 954.4 954.4 20 0 0 0 TSSTRN Training Services
20 SYS-LC-1260IIE 9EC 74 Erweit. Gewaehr. fuer Akad. - 2J, kompl. 1 5215 0 0 40 3129 3129 40 0 0 0 TSSYSX Academic Extended Warranty
21 R2005A RB Eingetauschte Geraete Deinst. und Vers. 1 0 0 0 0 0 0 0 0 0 0
1 # 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
2 1 G7111B 29 1260 Infinity II quaternaere Pumpe 1 25079 0 0 45 13793.45 13793.45 25 20 0 0 ISL100P1 Pumps
3 2 G7111B 001 29 HPLC System Tool Kit 1260 Infinity II 1 400 0 0 45 220 220 25 20 0 0
4 3 G7111B 030 29 Aktive Kolbenhinterspuelung 1 1463 0 0 45 804.65 804.65 25 20 0 0
5 4 G7111B 032 29 Aktiveinlassventil (AIV) 1 889 0 0 45 488.95 488.95 25 20 0 0
6 5 G7111B 094 29 Poroshell 120 EC-C18 3,0x150mm, 2,7um 1 1 0 0 45 0.55 0.55 25 20 0 0
7 6 G7129A 29 1260 Inf. II Fluessigprobengeber 1 19905 0 0 45 10947.75 10947.75 25 20 0 0 ISL100A1 Autosamplers
8 7 G7129A 010 29 Standard-Schublade (6x11 Probenflaschen) 1 375 0 0 45 206.25 206.25 25 20 0 0
9 8 G7129A 060 29 Nutzung vorhandene Lizenz 1 -1793 0 0 45 -986.15 -986.15 25 20 0 0
10 9 G7116A 29 1260 Infinity II Therm. f. mehr. Saeulen 1 6494 0 0 45 3571.7 3571.7 25 20 0 0 ISL100LC1 LC Hardware
11 10 G7116A 058 29 Ventilantrieb fuer 1260 Infinity II MCT 1 1541 0 0 45 847.55 847.55 25 20 0 0
12 11 G4237A 29 4Pos./10Anschl., 4-Saeulenausw. 800 bar 1 4808 0 0 45 2644.4 2644.4 25 20 0 0 ISL100LCV LC Valves
13 12 G4237A 006 29 Kapillarkit 0,17 mm, 4-Saeulen, m. QC-HE 1 3474 0 0 45 1910.7 1910.7 25 20 0 0
14 13 G7117C 29 1260 Infinity II Diodenarray-Detektor HS 1 24906 0 0 45 13698.3 13698.3 25 20 0 0 ISL100D1 Detectors
15 14 G7121B 29 1260 Infinity II FLD Spektren 1 21984 0 0 45 12091.2 12091.2 25 20 0 0 ISL100D1 Detectors
16 15 M8431AA LI OpenLab CDS Geraeteverbindung 1 1364 0 0 45 750.2 750.2 25 20 0 0 ISF300F100 OpenLAB CDS Software
17 16 M8431AA 001 LI LC-Geraeteverbindung 1 0 0 0 45 0 0 25 20 0 0
18 17 M8431AA 005 LI 3D UV/DAD-Verb. 1 0 0 0 45 0 0 25 20 0 0
19 18 SYS-LC-1260IIE 74 LC 1260 Infinity II System m. Zusatzfkt. 1 0 0 0 20 0 0 20 0 0 0 TSSYS0SYLC Service Systems - Liquid Chromatography
20 19 SYS-LC-1260IIE 2A9 74 Standard-Einweisung 1 1193 0 0 20 954.4 954.4 20 0 0 0 TSSTRN Training Services
21 20 SYS-LC-1260IIE 9EC 74 Erweit. Gewaehr. fuer Akad. - 2J, kompl. 1 5215 0 0 40 3129 3129 40 0 0 0 TSSYSX Academic Extended Warranty
22 21 R2005A RB Eingetauschte Geraete Deinst. und Vers. 1 0 0 0 0 0 0 0 0 0 0

@ -0,0 +1,22 @@
# 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 G7111B 29 1260 Infinity II quaternaere Pumpe 1 25079 0 0 45 13793.45 13793.45 25 20 0 0 ISL100P1 Pumps
2 G7111B 001 29 HPLC System Tool Kit 1260 Infinity II 1 400 0 0 45 220 220 25 20 0 0
3 G7111B 030 29 Aktive Kolbenhinterspuelung 1 1463 0 0 45 804.65 804.65 25 20 0 0
4 G7111B 032 29 Aktiveinlassventil (AIV) 1 889 0 0 45 488.95 488.95 25 20 0 0
5 G7111B 094 29 Poroshell 120 EC-C18 3,0x150mm, 2,7um 1 1 0 0 45 0.55 0.55 25 20 0 0
6 G7129A 29 1260 Inf. II Fluessigprobengeber 1 19905 0 0 45 10947.75 10947.75 25 20 0 0 ISL100A1 Autosamplers
7 G7129A 010 29 Standard-Schublade (6x11 Probenflaschen) 1 375 0 0 45 206.25 206.25 25 20 0 0
8 G7129A 060 29 Nutzung vorhandene Lizenz 1 -1793 0 0 45 -986.15 -986.15 25 20 0 0
9 G7116A 29 1260 Infinity II Therm. f. mehr. Saeulen 1 6494 0 0 45 3571.7 3571.7 25 20 0 0 ISL100LC1 LC Hardware
10 G7116A 058 29 Ventilantrieb fuer 1260 Infinity II MCT 1 1541 0 0 45 847.55 847.55 25 20 0 0
11 G4237A 29 4Pos./10Anschl., 4-Saeulenausw. 800 bar 1 4808 0 0 45 2644.4 2644.4 25 20 0 0 ISL100LCV LC Valves
12 G4237A 006 29 Kapillarkit 0,17 mm, 4-Saeulen, m. QC-HE 1 3474 0 0 45 1910.7 1910.7 25 20 0 0
13 G7117C 29 1260 Infinity II Diodenarray-Detektor HS 1 24906 0 0 45 13698.3 13698.3 25 20 0 0 ISL100D1 Detectors
14 G7121B 29 1260 Infinity II FLD Spektren 1 21984 0 0 45 12091.2 12091.2 25 20 0 0 ISL100D1 Detectors
15 M8431AA LI OpenLab CDS Geraeteverbindung 1 1364 0 0 45 750.2 750.2 25 20 0 0 ISF300F100 OpenLAB CDS Software
16 M8431AA 001 LI LC-Geraeteverbindung 1 0 0 0 45 0 0 25 20 0 0
17 M8431AA 005 LI 3D UV/DAD-Verb. 1 0 0 0 45 0 0 25 20 0 0
18 SYS-LC-1260IIE 74 LC 1260 Infinity II System m. Zusatzfkt. 1 0 0 0 20 0 0 20 0 0 0 TSSYS0SYLC Service Systems - Liquid Chromatography
19 SYS-LC-1260IIE 2A9 74 Standard-Einweisung 1 1193 0 0 20 954.4 954.4 20 0 0 0 TSSTRN Training Services
20 SYS-LC-1260IIE 9EC 74 Erweit. Gewaehr. fuer Akad. - 2J, kompl. 1 5215 0 0 40 3129 3129 40 0 0 0 TSSYSX Academic Extended Warranty
21 R2005A RB Eingetauschte Geraete Deinst. und Vers. 1 0 0 0 0 0 0 0 0 0 0
1 # 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
2 1 G7111B 29 1260 Infinity II quaternaere Pumpe 1 25079 0 0 45 13793.45 13793.45 25 20 0 0 ISL100P1 Pumps
3 2 G7111B 001 29 HPLC System Tool Kit 1260 Infinity II 1 400 0 0 45 220 220 25 20 0 0
4 3 G7111B 030 29 Aktive Kolbenhinterspuelung 1 1463 0 0 45 804.65 804.65 25 20 0 0
5 4 G7111B 032 29 Aktiveinlassventil (AIV) 1 889 0 0 45 488.95 488.95 25 20 0 0
6 5 G7111B 094 29 Poroshell 120 EC-C18 3,0x150mm, 2,7um 1 1 0 0 45 0.55 0.55 25 20 0 0
7 6 G7129A 29 1260 Inf. II Fluessigprobengeber 1 19905 0 0 45 10947.75 10947.75 25 20 0 0 ISL100A1 Autosamplers
8 7 G7129A 010 29 Standard-Schublade (6x11 Probenflaschen) 1 375 0 0 45 206.25 206.25 25 20 0 0
9 8 G7129A 060 29 Nutzung vorhandene Lizenz 1 -1793 0 0 45 -986.15 -986.15 25 20 0 0
10 9 G7116A 29 1260 Infinity II Therm. f. mehr. Saeulen 1 6494 0 0 45 3571.7 3571.7 25 20 0 0 ISL100LC1 LC Hardware
11 10 G7116A 058 29 Ventilantrieb fuer 1260 Infinity II MCT 1 1541 0 0 45 847.55 847.55 25 20 0 0
12 11 G4237A 29 4Pos./10Anschl., 4-Saeulenausw. 800 bar 1 4808 0 0 45 2644.4 2644.4 25 20 0 0 ISL100LCV LC Valves
13 12 G4237A 006 29 Kapillarkit 0,17 mm, 4-Saeulen, m. QC-HE 1 3474 0 0 45 1910.7 1910.7 25 20 0 0
14 13 G7117C 29 1260 Infinity II Diodenarray-Detektor HS 1 24906 0 0 45 13698.3 13698.3 25 20 0 0 ISL100D1 Detectors
15 14 G7121B 29 1260 Infinity II FLD Spektren 1 21984 0 0 45 12091.2 12091.2 25 20 0 0 ISL100D1 Detectors
16 15 M8431AA LI OpenLab CDS Geraeteverbindung 1 1364 0 0 45 750.2 750.2 25 20 0 0 ISF300F100 OpenLAB CDS Software
17 16 M8431AA 001 LI LC-Geraeteverbindung 1 0 0 0 45 0 0 25 20 0 0
18 17 M8431AA 005 LI 3D UV/DAD-Verb. 1 0 0 0 45 0 0 25 20 0 0
19 18 SYS-LC-1260IIE 74 LC 1260 Infinity II System m. Zusatzfkt. 1 0 0 0 20 0 0 20 0 0 0 TSSYS0SYLC Service Systems - Liquid Chromatography
20 19 SYS-LC-1260IIE 2A9 74 Standard-Einweisung 1 1193 0 0 20 954.4 954.4 20 0 0 0 TSSTRN Training Services
21 20 SYS-LC-1260IIE 9EC 74 Erweit. Gewaehr. fuer Akad. - 2J, kompl. 1 5215 0 0 40 3129 3129 40 0 0 0 TSSYSX Academic Extended Warranty
22 21 R2005A RB Eingetauschte Geraete Deinst. und Vers. 1 0 0 0 0 0 0 0 0 0 0

@ -0,0 +1,181 @@
\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-423-223}
\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{Preisinformation}}}}
\end{flushright}
\begin{tabular}{p{0.4\hsize}p{0.6\hsize}}
&
\multirow{4}{*}{
\begin{tabular}{|ll|}
\hline
\textbf{Angebotsnummer:}&DE-83PE89-423-223\\
Angebotdatum:&\today\\
Angebotsgültigkeit:&60 Tage\\\textbf{Ansprechpartner:}&Sascha Woitschetzki\\
Telefon: &+49 208 74129134\\
Mobil:&+49 176 22285334\\
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 Kristina Witzler
\\
Institut für Arbeitsschutz der Deutschen Gesetzlic
\\
Alte Heerstr. 111
\\
53757 Sankt augustin
\\
&\\
&\\
\end{tabular}
\vspace{1cm}\par
Sehr geehrte Frau Witzler,\par
nachfolgend erhalten Sie Ihr gewünschtes Angebot über ein(e) HPLC.\\
Es umfasst im Einzelnen:
\begin{itemize}
\item quaternäre Pumpe mit integriertem Entgaser (\#1)
\begin{itemize}
\item Werkzeugsatz (\#2)
\item Aktive Kolbenhinterspülung (\#3)
\item Aktives Einlassventil (\#4)
\item Säule (\#5)
\end{itemize}
\item Vialsampler (\#6)
\begin{itemize}
\item Probenteller für 6x11 2,0 ml Vials (\#7)
\item Ohne Gerätetreiber (\#8)
\end{itemize}
\item Säulenthermostat (\#9)
\begin{itemize}
\item Ventilantrieb (\#10)
\end{itemize}
\item 4-Säulenauswahlventil (\#11)
\begin{itemize}
\item Kapillarkit (\#12)
\end{itemize}
\item Diodenarraydetektor High Sensitivity (\#13)
\begin{itemize}
\item Max-Light-Kartuschenzelle (\#14)
\end{itemize}
\item Fluoreszenzspektrendetektor (\#15)
\item OpenLab CDS 2 Instrument Connection (\#16)
\begin{itemize}
\item OpenLab CDS 2 IC für LC (\#17)
\item OpenLab CDS 2 IC für 3D-UV/DAD (\#18)
\end{itemize}
\item 1260 Infinity II HPLC mit Zusatzfunktionen (\#19)
\begin{itemize}
\item Einführung (\#20)
\item Zwei Jahre Gewährleistung (\#21)
\item Silber-Vertrag (Laufzeit: 2 Jahre) (\#22)
\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{Quaternäre Pumpe} (G7111B)\newline 1260 Infinity II quaternäre Pumpe, Maximaldruck 600 bar. Mit integriertem 4-Kanal-Entgaser, vergünstigter Säule, Verbindungskapillaren, Lösemittelwanne und -flaschen.&1&\SI{17555.3}{\sieuro}\\
2 &\textbf{Werkzeugsatz} (G7111B\#001)\newline HPLC System Tool Kit, für Agilent 1260/1290 Infinity II LC.&1&\SI{280}{\sieuro}\\
3 &\textbf{Aktive Kolbenhinterspülung} (G7111B\#030)\newline Automatische Reinigung und Pflege der Pumpenköpfe, -dichtungen und -ventile für maximale Lebensdauer. Besonders empfohlen bei salzhaltigen Analyten oder Puffern.&1&\SI{1024.1}{\sieuro}\\
4 &\textbf{Aktives Einlassventil} (G7111B\#032)\newline Aktives Einlassventil (AIV) für einen zuverlässigen Pumpenbetrieb bei der Verwendung von Puffern.&1&\SI{622.3}{\sieuro}\\
5 &\textbf{Säule} (G7111B\#094)\newline InfinityLab Poroshell 120 EC-C18, 3.0 x 150 mm, 2.7 µm.&1&\SI{0.7}{\sieuro}\\
6 &\textbf{Vialsampler} (G7129A)\newline 1260 Infinity II automatischer Flüssigprobengeber zur Verwendung bei bis zu 600 bar. Mit integriertem Nadelspülanschluss zur Minimierung der Verschleppung, 100 µl Dosiereinheit und 100 µl Probenschleife. Inklusive Gerätetreiber für ein LC-System (2D-UV).&1&\SI{13933.5}{\sieuro}\\
7 &\textbf{Probenteller für 6x11 2,0 ml Vials} (G7129A\#010)\newline &1&\SI{262.5}{\sieuro}\\
8 &\textbf{Ohne Gerätetreiber} (G7129A\#060)\newline Es wird ein vorhandener Gerätetreiber verwendet oder mit der Software angeboten.&1&\SI{-1255.1}{\sieuro}\\
9 &\textbf{Säulenthermostat} (G7116A)\newline 1260 Infinity II Thermostat für bis zu vier 30 cm Säulen, Temperaturbereich: 10° unter Raumtemperatur (min. 4 °C) bis max. 85 °C, inkl. Säulenidentifikations-Kit. Ventilantrieb optional.&1&\SI{4545.8}{\sieuro}\\
10 &\textbf{Ventilantrieb} (G7116A\#058)\newline Ventilantrieb für 1260 Infinity II Thermostat G7116A. Zur Verwendung mit QuickChange-Ventilköpfen.&1&\SI{1078.7}{\sieuro}\\
11 &\textbf{4-Säulenauswahlventil} (G4237A)\newline QuickChange-Ventilkopf zur Auswahl von 4 Säulen (4Pos./10 Anschlüsse), max. 800 bar. Zum schnellen Säulenwechsel oder Schaltung eines Bypasses zur Direktaufgabe auf das Massenspektrometer.&1&\SI{3365.6}{\sieuro}\\
12 &\textbf{Kapillarkit} (G4237A\#006)\newline 4-Säulenauswahlventil-Kapillarkit, Inhalt: 0,17 mm ID Kapillaren und vier Quick Connect-Wärmetauscher, zur Verwendung in G7116A.&1&\SI{2431.8}{\sieuro}\\
13 &\textbf{Diodenarraydetektor HS} (G7117C)\newline 1260 Infinity II Diodenarray-Detektor high sensitivity für höchste Empfindlichkeit, 120 Hz Datenrate für schnelle Multiwellenlängen- und Spektralanalysen. Messbereich 190 640 nm, RFID-Tags für Zelle und Lampe. Inklusive Standard-Max-Light-Flusszelle (10 mm, V = 1 µl, max. 70 bar).&1&\SI{17434.2}{\sieuro}\\
14 &\textbf{Max-Light-Kartuschenzelle} (G7117C\#031)\newline Zusätzliche 60 mm Max-Light-Kartuschenzelle mit hoher Empfindlichkeit und einem Zellvolumen von 4 ul&1&\SI{2634.1}{\sieuro}\\
15 &\textbf{Fluoreszenzspektrendetektor} (G7121B)\newline 1260 Infinity II Fluoreszenzdetektor, spektrenfähig.\newline Für Multiwellenlängen-Detektion, Online-Aufnahme von  Anregungs- und Emissionsspektren (200 1200 nm), Datenrate bis 148 Hz. Inkl. Standard-Durchflusszelle (V = 8 µl, max. 20 bar).&1&\SI{15388.8}{\sieuro}\\
16 &\textbf{OpenLab CDS 2 Instrument Connection} (M8431AA)\newline &1&\SI{954.8}{\sieuro}\\
17 &\textbf{OpenLab CDS 2 IC für LC} (M8431AA\#001)\newline Lizenz und Treiber zur Gerätesteuerung unter OpenLab CDS. Gerätetyp: LC (ohne DAD)&1&\SI{0}{\sieuro}\\
18 &\textbf{OpenLab CDS 2 IC für 3D-UV/DAD} (M8431AA\#005)\newline Lizenz und Treiber zur Gerätesteuerung unter OpenLab CDS. Gerätetyp: 3D-UV/DAD&1&\SI{0}{\sieuro}\\
19 &\textbf{1260 Infinity II HPLC mit Zusatzfunktionen} (SYS-LC-1260IIE)\newline &1&\SI{0}{\sieuro}\\
20 &\textbf{Einführung} (SYS-LC-1260IIE\#2A9)\newline Standardeinweisung für neue Anwender im Rahmen der Installation.&1&\SI{954.4}{\sieuro}\\
21 &\textbf{Erweiterte Gewährleistung für akademische Kunden, zwei Jahre komplett} (SYS-LC-1260IIE\#9EC)\newline Verlängerung der Gewährleistung von 12 auf 24 Monate.&1&\SI{4172}{\sieuro}\\
22 &\textbf{Silber-Wartungsvertrag} (SYS-LC-1260IIE\#8R2)\newline Laufzeit: 2 Jahre.&1&\SI{9444.75}{\sieuro}\\
\hline
\end{longtable}
\end{center}
\vspace{-2cm}
\begin{flushright}
\begin{tabular}{|rr|}
\hline
\textbf{Summe netto} & \SI{94828.25}{\sieuro}\\
\textbf{Versand und Bereitstellungskosten (3\%)} & \SI{2844.8475}{\sieuro}\\
\textbf{Gesamtsumme netto} & \SI{97673.0975}{\sieuro}\\
\textbf{Umsatzsteuer (19\%)} & \SI{18557.888525}{\sieuro}\\
\textbf{Gesamtsumme brutto} & \SI{116230.986025}{\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 24 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}

@ -0,0 +1,23 @@
# 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 G7111B 29 1260 Infinity II quaternaere Pumpe 1 25079 0 0 30 17555.3 17555.3 30 0 0 0 ISL100P1 Pumps
2 G7111B 001 29 HPLC System Tool Kit 1260 Infinity II 1 400 0 0 30 280 280 30 0 0 0
3 G7111B 030 29 Aktive Kolbenhinterspuelung 1 1463 0 0 30 1024.1 1024.1 30 0 0 0
4 G7111B 032 29 Aktiveinlassventil (AIV) 1 889 0 0 30 622.3 622.3 30 0 0 0
5 G7111B 094 29 Poroshell 120 EC-C18 3,0x150mm, 2,7um 1 1 0 0 30 0.7 0.7 30 0 0 0
6 G7129A 29 1260 Inf. II Fluessigprobengeber 1 19905 0 0 30 13933.5 13933.5 30 0 0 0 ISL100A1 Autosamplers
7 G7129A 010 29 Standard-Schublade (6x11 Probenflaschen) 1 375 0 0 30 262.5 262.5 30 0 0 0
8 G7129A 060 29 Nutzung vorhandene Lizenz 1 -1793 0 0 30 -1255.1 -1255.1 30 0 0 0
9 G7116A 29 1260 Infinity II Therm. f. mehr. Saeulen 1 6494 0 0 30 4545.8 4545.8 30 0 0 0 ISL100LC1 LC Hardware
10 G7116A 058 29 Ventilantrieb fuer 1260 Infinity II MCT 1 1541 0 0 30 1078.7 1078.7 30 0 0 0
11 G4237A 29 4Pos./10Anschl., 4-Saeulenausw. 800 bar 1 4808 0 0 30 3365.6 3365.6 30 0 0 0 ISL100LCV LC Valves
12 G4237A 006 29 Kapillarkit 0,17 mm, 4-Saeulen, m. QC-HE 1 3474 0 0 30 2431.8 2431.8 30 0 0 0
13 G7117C 29 1260 Infinity II Diodenarray-Detektor HS 1 24906 0 0 30 17434.2 17434.2 30 0 0 0 ISL100D1 Detectors
14 G7117C 031 29 Max-Light Kart.-Zelle 60 mm hinzufuegen 1 3763 0 0 30 2634.1 2634.1 30 0 0 0
15 G7121B 29 1260 Infinity II FLD Spektren 1 21984 0 0 30 15388.8 15388.8 30 0 0 0 ISL100D1 Detectors
16 M8431AA LI OpenLab CDS Geraeteverbindung 1 1364 0 0 30 954.8 954.8 30 0 0 0 ISF300F100 OpenLAB CDS Software
17 M8431AA 001 LI LC-Geraeteverbindung 1 0 0 0 30 0 0 30 0 0 0
18 M8431AA 005 LI 3D UV/DAD-Verb. 1 0 0 0 30 0 0 30 0 0 0
19 SYS-LC-1260IIE 74 LC 1260 Infinity II System m. Zusatzfkt. 1 0 0 0 20 0 0 20 0 0 0 TSSYS0SYLC Service Systems - Liquid Chromatography
20 SYS-LC-1260IIE 2A9 74 Standard-Einweisung 1 1193 0 0 20 954.4 954.4 20 0 0 0 TSSTRN Training Services
21 SYS-LC-1260IIE 9EC 74 Erweit. Gewaehr. fuer Akad. - 2J, kompl. 1 5215 0 0 20 4172 4172 20 0 0 0 TSSYSX Academic Extended Warranty
22 SYS-LC-1260IIE 8R2 74 CrossLab Silver - 2J, kompl. 1 12593 0 0 25 9444.75 9444.75 20 0 5 0 TSSYS2 Serviced As Systems - 2 YR
1 # 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
2 1 G7111B 29 1260 Infinity II quaternaere Pumpe 1 25079 0 0 30 17555.3 17555.3 30 0 0 0 ISL100P1 Pumps
3 2 G7111B 001 29 HPLC System Tool Kit 1260 Infinity II 1 400 0 0 30 280 280 30 0 0 0
4 3 G7111B 030 29 Aktive Kolbenhinterspuelung 1 1463 0 0 30 1024.1 1024.1 30 0 0 0
5 4 G7111B 032 29 Aktiveinlassventil (AIV) 1 889 0 0 30 622.3 622.3 30 0 0 0
6 5 G7111B 094 29 Poroshell 120 EC-C18 3,0x150mm, 2,7um 1 1 0 0 30 0.7 0.7 30 0 0 0
7 6 G7129A 29 1260 Inf. II Fluessigprobengeber 1 19905 0 0 30 13933.5 13933.5 30 0 0 0 ISL100A1 Autosamplers
8 7 G7129A 010 29 Standard-Schublade (6x11 Probenflaschen) 1 375 0 0 30 262.5 262.5 30 0 0 0
9 8 G7129A 060 29 Nutzung vorhandene Lizenz 1 -1793 0 0 30 -1255.1 -1255.1 30 0 0 0
10 9 G7116A 29 1260 Infinity II Therm. f. mehr. Saeulen 1 6494 0 0 30 4545.8 4545.8 30 0 0 0 ISL100LC1 LC Hardware
11 10 G7116A 058 29 Ventilantrieb fuer 1260 Infinity II MCT 1 1541 0 0 30 1078.7 1078.7 30 0 0 0
12 11 G4237A 29 4Pos./10Anschl., 4-Saeulenausw. 800 bar 1 4808 0 0 30 3365.6 3365.6 30 0 0 0 ISL100LCV LC Valves
13 12 G4237A 006 29 Kapillarkit 0,17 mm, 4-Saeulen, m. QC-HE 1 3474 0 0 30 2431.8 2431.8 30 0 0 0
14 13 G7117C 29 1260 Infinity II Diodenarray-Detektor HS 1 24906 0 0 30 17434.2 17434.2 30 0 0 0 ISL100D1 Detectors
15 14 G7117C 031 29 Max-Light Kart.-Zelle 60 mm hinzufuegen 1 3763 0 0 30 2634.1 2634.1 30 0 0 0
16 15 G7121B 29 1260 Infinity II FLD Spektren 1 21984 0 0 30 15388.8 15388.8 30 0 0 0 ISL100D1 Detectors
17 16 M8431AA LI OpenLab CDS Geraeteverbindung 1 1364 0 0 30 954.8 954.8 30 0 0 0 ISF300F100 OpenLAB CDS Software
18 17 M8431AA 001 LI LC-Geraeteverbindung 1 0 0 0 30 0 0 30 0 0 0
19 18 M8431AA 005 LI 3D UV/DAD-Verb. 1 0 0 0 30 0 0 30 0 0 0
20 19 SYS-LC-1260IIE 74 LC 1260 Infinity II System m. Zusatzfkt. 1 0 0 0 20 0 0 20 0 0 0 TSSYS0SYLC Service Systems - Liquid Chromatography
21 20 SYS-LC-1260IIE 2A9 74 Standard-Einweisung 1 1193 0 0 20 954.4 954.4 20 0 0 0 TSSTRN Training Services
22 21 SYS-LC-1260IIE 9EC 74 Erweit. Gewaehr. fuer Akad. - 2J, kompl. 1 5215 0 0 20 4172 4172 20 0 0 0 TSSYSX Academic Extended Warranty
23 22 SYS-LC-1260IIE 8R2 74 CrossLab Silver - 2J, kompl. 1 12593 0 0 25 9444.75 9444.75 20 0 5 0 TSSYS2 Serviced As Systems - 2 YR

@ -0,0 +1,177 @@
\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-423-224}
\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{Preisinformation}}}}
\end{flushright}
\begin{tabular}{p{0.4\hsize}p{0.6\hsize}}
&
\multirow{4}{*}{
\begin{tabular}{|ll|}
\hline
\textbf{Angebotsnummer:}&DE-83PE89-423-224\\
Angebotdatum:&\today\\
Angebotsgültigkeit:&90 Tage\\\textbf{Ansprechpartner:}&Sascha Woitschetzki\\
Telefon: &+49 208 74129134\\
Mobil:&+49 176 22285334\\
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 Kristina Witzler
\\
Institut für Arbeitsschutz der Deutschen Gesetzlic
\\
Alte Heerstr. 111
\\
53757 Sankt augustin
\\
&\\
&\\
\end{tabular}
\vspace{1cm}\par
Sehr geehrte Frau Witzler,\par
nachfolgend erhalten Sie Ihr gewünschtes Angebot über ein(e) HPLC.\\
Es umfasst im Einzelnen:
\begin{itemize}
\item quaternäre Pumpe mit integriertem Entgaser (\#1)
\begin{itemize}
\item Werkzeugsatz (\#2)
\item Aktive Kolbenhinterspülung (\#3)
\item Aktives Einlassventil (\#4)
\item Säule (\#5)
\end{itemize}
\item Vialsampler (\#6)
\begin{itemize}
\item Probenteller für 6x11 2,0 ml Vials (\#7)
\item Ohne Gerätetreiber (\#8)
\end{itemize}
\item Säulenthermostat (\#9)
\begin{itemize}
\item Ventilantrieb (\#10)
\end{itemize}
\item 4-Säulenauswahlventil (\#11)
\begin{itemize}
\item Kapillarkit (\#12)
\end{itemize}
\item Diodenarraydetektor High Sensitivity (\#13)
\item Fluoreszenzspektrendetektor (\#14)
\item OpenLab CDS 2 Instrument Connection (\#15)
\begin{itemize}
\item OpenLab CDS 2 IC für LC (\#16)
\item OpenLab CDS 2 IC für 3D-UV/DAD (\#17)
\end{itemize}
\item 1260 Infinity II HPLC mit Zusatzfunktionen (\#18)
\begin{itemize}
\item Einführung (\#19)
\item Zwei Jahre Gewährleistung (\#20)
\end{itemize}
\item Überprüfung, Deinstallation und Versand (\#21)
\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{Quaternäre Pumpe} (G7111B)\newline 1260 Infinity II quaternäre Pumpe, Maximaldruck 600 bar. Mit integriertem 4-Kanal-Entgaser, vergünstigter Säule, Verbindungskapillaren, Lösemittelwanne und -flaschen.\newline Listenpreis: \SI{25079}{\sieuro}&1&\SI{45}{\%}&\SI{13793.45}{\sieuro}\\
2 &\textbf{Werkzeugsatz} (G7111B\#001)\newline HPLC System Tool Kit, für Agilent 1260/1290 Infinity II LC.\newline Listenpreis: \SI{400}{\sieuro}&1&\SI{45}{\%}&\SI{220}{\sieuro}\\
3 &\textbf{Aktive Kolbenhinterspülung} (G7111B\#030)\newline Automatische Reinigung und Pflege der Pumpenköpfe, -dichtungen und -ventile für maximale Lebensdauer. Besonders empfohlen bei salzhaltigen Analyten oder Puffern.\newline Listenpreis: \SI{1463}{\sieuro}&1&\SI{45}{\%}&\SI{804.65}{\sieuro}\\
4 &\textbf{Aktives Einlassventil} (G7111B\#032)\newline Aktives Einlassventil (AIV) für einen zuverlässigen Pumpenbetrieb bei der Verwendung von Puffern.\newline Listenpreis: \SI{889}{\sieuro}&1&\SI{45}{\%}&\SI{488.95}{\sieuro}\\
5 &\textbf{Säule} (G7111B\#094)\newline InfinityLab Poroshell 120 EC-C18, 3.0 x 150 mm, 2.7 µm.\newline Listenpreis: \SI{1}{\sieuro}&1&\SI{45}{\%}&\SI{0.55}{\sieuro}\\
6 &\textbf{Vialsampler} (G7129A)\newline 1260 Infinity II automatischer Flüssigprobengeber zur Verwendung bei bis zu 600 bar. Mit integriertem Nadelspülanschluss zur Minimierung der Verschleppung, 100 µl Dosiereinheit und 100 µl Probenschleife. Inklusive Gerätetreiber für ein LC-System (2D-UV).\newline Listenpreis: \SI{19905}{\sieuro}&1&\SI{45}{\%}&\SI{10947.75}{\sieuro}\\
7 &\textbf{Probenteller für 6x11 2,0 ml Vials} (G7129A\#010)\newline \newline Listenpreis: \SI{375}{\sieuro}&1&\SI{45}{\%}&\SI{206.25}{\sieuro}\\
8 &\textbf{Ohne Gerätetreiber} (G7129A\#060)\newline Es wird ein vorhandener Gerätetreiber verwendet oder mit der Software angeboten.\newline Listenpreis: \SI{-1793}{\sieuro}&1&\SI{45}{\%}&\SI{-986.15}{\sieuro}\\
9 &\textbf{Säulenthermostat} (G7116A)\newline 1260 Infinity II Thermostat für bis zu vier 30 cm Säulen, Temperaturbereich: 10° unter Raumtemperatur (min. 4 °C) bis max. 85 °C, inkl. Säulenidentifikations-Kit. Ventilantrieb optional.\newline Listenpreis: \SI{6494}{\sieuro}&1&\SI{45}{\%}&\SI{3571.7}{\sieuro}\\
10 &\textbf{Ventilantrieb} (G7116A\#058)\newline Ventilantrieb für 1260 Infinity II Thermostat G7116A. Zur Verwendung mit QuickChange-Ventilköpfen.\newline Listenpreis: \SI{1541}{\sieuro}&1&\SI{45}{\%}&\SI{847.55}{\sieuro}\\
11 &\textbf{4-Säulenauswahlventil} (G4237A)\newline QuickChange-Ventilkopf zur Auswahl von 4 Säulen (4Pos./10 Anschlüsse), max. 800 bar. Zum schnellen Säulenwechsel oder Schaltung eines Bypasses zur Direktaufgabe auf das Massenspektrometer.\newline Listenpreis: \SI{4808}{\sieuro}&1&\SI{45}{\%}&\SI{2644.4}{\sieuro}\\
12 &\textbf{Kapillarkit} (G4237A\#006)\newline 4-Säulenauswahlventil-Kapillarkit, Inhalt: 0,17 mm ID Kapillaren und vier Quick Connect-Wärmetauscher, zur Verwendung in G7116A.\newline Listenpreis: \SI{3474}{\sieuro}&1&\SI{45}{\%}&\SI{1910.7}{\sieuro}\\
13 &\textbf{Diodenarraydetektor HS} (G7117C)\newline 1260 Infinity II Diodenarray-Detektor high sensitivity für höchste Empfindlichkeit, 120 Hz Datenrate für schnelle Multiwellenlängen- und Spektralanalysen. Messbereich 190 640 nm, RFID-Tags für Zelle und Lampe. Inklusive Standard-Max-Light-Flusszelle (10 mm, V = 1 µl, max. 70 bar).\newline Listenpreis: \SI{24906}{\sieuro}&1&\SI{45}{\%}&\SI{13698.3}{\sieuro}\\
14 &\textbf{Fluoreszenzspektrendetektor} (G7121B)\newline 1260 Infinity II Fluoreszenzdetektor, spektrenfähig.\newline Für Multiwellenlängen-Detektion, Online-Aufnahme von  Anregungs- und Emissionsspektren (200 1200 nm), Datenrate bis 148 Hz. Inkl. Standard-Durchflusszelle (V = 8 µl, max. 20 bar).\newline Listenpreis: \SI{21984}{\sieuro}&1&\SI{45}{\%}&\SI{12091.2}{\sieuro}\\
15 &\textbf{OpenLab CDS 2 Instrument Connection} (M8431AA)\newline \newline Listenpreis: \SI{1364}{\sieuro}&1&\SI{45}{\%}&\SI{750.2}{\sieuro}\\
16 &\textbf{OpenLab CDS 2 IC für LC} (M8431AA\#001)\newline Lizenz und Treiber zur Gerätesteuerung unter OpenLab CDS. Gerätetyp: LC (ohne DAD)\newline Listenpreis: \SI{0}{\sieuro}&1&\SI{45}{\%}&\SI{0}{\sieuro}\\
17 &\textbf{OpenLab CDS 2 IC für 3D-UV/DAD} (M8431AA\#005)\newline Lizenz und Treiber zur Gerätesteuerung unter OpenLab CDS. Gerätetyp: 3D-UV/DAD\newline Listenpreis: \SI{0}{\sieuro}&1&\SI{45}{\%}&\SI{0}{\sieuro}\\
18 &\textbf{1260 Infinity II HPLC mit Zusatzfunktionen} (SYS-LC-1260IIE)\newline \newline Listenpreis: \SI{0}{\sieuro}&1&\SI{20}{\%}&\SI{0}{\sieuro}\\
19 &\textbf{Einführung} (SYS-LC-1260IIE\#2A9)\newline Standardeinweisung für neue Anwender im Rahmen der Installation.\newline Listenpreis: \SI{1193}{\sieuro}&1&\SI{20}{\%}&\SI{954.4}{\sieuro}\\
20 &\textbf{Erweiterte Gewährleistung für akademische Kunden, zwei Jahre komplett} (SYS-LC-1260IIE\#9EC)\newline Verlängerung der Gewährleistung von 12 auf 24 Monate.\newline Listenpreis: \SI{5215}{\sieuro}&1&\SI{40}{\%}&\SI{3129}{\sieuro}\\
21 &\textbf{Überprüfung, Deinstallation und Versand} (R2005A)\newline Überprüfung, Deinstallation und Versand der in Zahlung gegebenen Geräte.\newline Die erfolgreiche Überprüfung der Geräte durch einen Agilent Techniker ist Voraussetzung für die Annahme der Inzahlungnahme durch Agilent.\newline Listenpreis: \SI{0}{\sieuro}&1&\SI{0}{\%}&\SI{0}{\sieuro}\\
\hline
\end{longtable}
\end{center}
\vspace{-2cm}
\begin{flushright}
\begin{tabular}{|rr|}
\hline
\textbf{Summe netto} & \SI{65072.90}{\sieuro}\\
\textbf{Versand und Bereitstellungskosten (3\%)} & \SI{1952.187}{\sieuro}\\
\textbf{Gesamtsumme netto} & \SI{67025.087}{\sieuro}\\
\textbf{Umsatzsteuer (19\%)} & \SI{12734.76653}{\sieuro}\\
\textbf{Gesamtsumme brutto} & \SI{79759.85353}{\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 24 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}

@ -0,0 +1,22 @@
# 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 G7111B 29 1260 Infinity II quaternaere Pumpe 1 25079 0 0 45 13793.45 13793.45 25 20 0 0 ISL100P1 Pumps
2 G7111B 001 29 HPLC System Tool Kit 1260 Infinity II 1 400 0 0 45 220 220 25 20 0 0
3 G7111B 030 29 Aktive Kolbenhinterspuelung 1 1463 0 0 45 804.65 804.65 25 20 0 0
4 G7111B 032 29 Aktiveinlassventil (AIV) 1 889 0 0 45 488.95 488.95 25 20 0 0
5 G7111B 094 29 Poroshell 120 EC-C18 3,0x150mm, 2,7um 1 1 0 0 45 0.55 0.55 25 20 0 0
6 G7129A 29 1260 Inf. II Fluessigprobengeber 1 19905 0 0 45 10947.75 10947.75 25 20 0 0 ISL100A1 Autosamplers
7 G7129A 010 29 Standard-Schublade (6x11 Probenflaschen) 1 375 0 0 45 206.25 206.25 25 20 0 0
8 G7129A 060 29 Nutzung vorhandene Lizenz 1 -1793 0 0 45 -986.15 -986.15 25 20 0 0
9 G7116A 29 1260 Infinity II Therm. f. mehr. Saeulen 1 6494 0 0 45 3571.7 3571.7 25 20 0 0 ISL100LC1 LC Hardware
10 G7116A 058 29 Ventilantrieb fuer 1260 Infinity II MCT 1 1541 0 0 45 847.55 847.55 25 20 0 0
11 G4237A 29 4Pos./10Anschl., 4-Saeulenausw. 800 bar 1 4808 0 0 45 2644.4 2644.4 25 20 0 0 ISL100LCV LC Valves
12 G4237A 006 29 Kapillarkit 0,17 mm, 4-Saeulen, m. QC-HE 1 3474 0 0 45 1910.7 1910.7 25 20 0 0
13 G7117C 29 1260 Infinity II Diodenarray-Detektor HS 1 24906 0 0 45 13698.3 13698.3 25 20 0 0 ISL100D1 Detectors
14 G7121B 29 1260 Infinity II FLD Spektren 1 21984 0 0 45 12091.2 12091.2 25 20 0 0 ISL100D1 Detectors
15 M8431AA LI OpenLab CDS Geraeteverbindung 1 1364 0 0 45 750.2 750.2 25 20 0 0 ISF300F100 OpenLAB CDS Software
16 M8431AA 001 LI LC-Geraeteverbindung 1 0 0 0 45 0 0 25 20 0 0
17 M8431AA 005 LI 3D UV/DAD-Verb. 1 0 0 0 45 0 0 25 20 0 0
18 SYS-LC-1260IIE 74 LC 1260 Infinity II System m. Zusatzfkt. 1 0 0 0 20 0 0 20 0 0 0 TSSYS0SYLC Service Systems - Liquid Chromatography
19 SYS-LC-1260IIE 2A9 74 Standard-Einweisung 1 1193 0 0 20 954.4 954.4 20 0 0 0 TSSTRN Training Services
20 SYS-LC-1260IIE 9EC 74 Erweit. Gewaehr. fuer Akad. - 2J, kompl. 1 5215 0 0 40 3129 3129 40 0 0 0 TSSYSX Academic Extended Warranty
21 R2005A RB Eingetauschte Geraete Deinst. und Vers. 1 0 0 0 0 0 0 0 0 0 0
1 # 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
2 1 G7111B 29 1260 Infinity II quaternaere Pumpe 1 25079 0 0 45 13793.45 13793.45 25 20 0 0 ISL100P1 Pumps
3 2 G7111B 001 29 HPLC System Tool Kit 1260 Infinity II 1 400 0 0 45 220 220 25 20 0 0
4 3 G7111B 030 29 Aktive Kolbenhinterspuelung 1 1463 0 0 45 804.65 804.65 25 20 0 0
5 4 G7111B 032 29 Aktiveinlassventil (AIV) 1 889 0 0 45 488.95 488.95 25 20 0 0
6 5 G7111B 094 29 Poroshell 120 EC-C18 3,0x150mm, 2,7um 1 1 0 0 45 0.55 0.55 25 20 0 0
7 6 G7129A 29 1260 Inf. II Fluessigprobengeber 1 19905 0 0 45 10947.75 10947.75 25 20 0 0 ISL100A1 Autosamplers
8 7 G7129A 010 29 Standard-Schublade (6x11 Probenflaschen) 1 375 0 0 45 206.25 206.25 25 20 0 0
9 8 G7129A 060 29 Nutzung vorhandene Lizenz 1 -1793 0 0 45 -986.15 -986.15 25 20 0 0
10 9 G7116A 29 1260 Infinity II Therm. f. mehr. Saeulen 1 6494 0 0 45 3571.7 3571.7 25 20 0 0 ISL100LC1 LC Hardware
11 10 G7116A 058 29 Ventilantrieb fuer 1260 Infinity II MCT 1 1541 0 0 45 847.55 847.55 25 20 0 0
12 11 G4237A 29 4Pos./10Anschl., 4-Saeulenausw. 800 bar 1 4808 0 0 45 2644.4 2644.4 25 20 0 0 ISL100LCV LC Valves
13 12 G4237A 006 29 Kapillarkit 0,17 mm, 4-Saeulen, m. QC-HE 1 3474 0 0 45 1910.7 1910.7 25 20 0 0
14 13 G7117C 29 1260 Infinity II Diodenarray-Detektor HS 1 24906 0 0 45 13698.3 13698.3 25 20 0 0 ISL100D1 Detectors
15 14 G7121B 29 1260 Infinity II FLD Spektren 1 21984 0 0 45 12091.2 12091.2 25 20 0 0 ISL100D1 Detectors
16 15 M8431AA LI OpenLab CDS Geraeteverbindung 1 1364 0 0 45 750.2 750.2 25 20 0 0 ISF300F100 OpenLAB CDS Software
17 16 M8431AA 001 LI LC-Geraeteverbindung 1 0 0 0 45 0 0 25 20 0 0
18 17 M8431AA 005 LI 3D UV/DAD-Verb. 1 0 0 0 45 0 0 25 20 0 0
19 18 SYS-LC-1260IIE 74 LC 1260 Infinity II System m. Zusatzfkt. 1 0 0 0 20 0 0 20 0 0 0 TSSYS0SYLC Service Systems - Liquid Chromatography
20 19 SYS-LC-1260IIE 2A9 74 Standard-Einweisung 1 1193 0 0 20 954.4 954.4 20 0 0 0 TSSTRN Training Services
21 20 SYS-LC-1260IIE 9EC 74 Erweit. Gewaehr. fuer Akad. - 2J, kompl. 1 5215 0 0 40 3129 3129 40 0 0 0 TSSYSX Academic Extended Warranty
22 21 R2005A RB Eingetauschte Geraete Deinst. und Vers. 1 0 0 0 0 0 0 0 0 0 0

@ -0,0 +1,177 @@
\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-423-225}
\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{Preisinformation}}}}
\end{flushright}
\begin{tabular}{p{0.4\hsize}p{0.6\hsize}}
&
\multirow{4}{*}{
\begin{tabular}{|ll|}
\hline
\textbf{Angebotsnummer:}&DE-83PE89-423-225\\
Angebotdatum:&\today\\
Angebotsgültigkeit:&60 Tage\\\textbf{Ansprechpartner:}&Sascha Woitschetzki\\
Telefon: &+49 208 74129134\\
Mobil:&+49 176 22285334\\
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 Kristina Witzler
\\
Institut für Arbeitsschutz der Deutschen Gesetzlic
\\
Alte Heerstr. 111
\\
53757 Sankt augustin
\\
&\\
&\\
\end{tabular}
\vspace{1cm}\par
Sehr geehrte Frau Witzler,\par
nachfolgend erhalten Sie Ihr gewünschtes Angebot über ein(e) HPLC.\\
Es umfasst im Einzelnen:
\begin{itemize}
\item quaternäre Pumpe mit integriertem Entgaser (\#1)
\begin{itemize}
\item Werkzeugsatz (\#2)
\item Aktive Kolbenhinterspülung (\#3)
\item Aktives Einlassventil (\#4)
\item Säule (\#5)
\end{itemize}
\item Vialsampler (\#6)
\begin{itemize}
\item Probenteller für 6x11 2,0 ml Vials (\#7)
\item Ohne Gerätetreiber (\#8)
\end{itemize}
\item Säulenthermostat (\#9)
\begin{itemize}
\item Ventilantrieb (\#10)
\end{itemize}
\item 4-Säulenauswahlventil (\#11)
\begin{itemize}
\item Kapillarkit (\#12)
\end{itemize}
\item Diodenarraydetektor High Sensitivity (\#13)
\item Fluoreszenzspektrendetektor (\#14)
\item OpenLab CDS 2 Instrument Connection (\#15)
\begin{itemize}
\item OpenLab CDS 2 IC für LC (\#16)
\item OpenLab CDS 2 IC für 3D-UV/DAD (\#17)
\end{itemize}
\item 1260 Infinity II HPLC mit Zusatzfunktionen (\#18)
\begin{itemize}
\item Einführung (\#19)
\item Zwei Jahre Gewährleistung (\#20)
\end{itemize}
\item Überprüfung, Deinstallation und Versand (\#21)
\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{Quaternäre Pumpe} (G7111B)\newline 1260 Infinity II quaternäre Pumpe, Maximaldruck 600 bar. Mit integriertem 4-Kanal-Entgaser, vergünstigter Säule, Verbindungskapillaren, Lösemittelwanne und -flaschen.\newline Listenpreis: \SI{25079}{\sieuro}&1&\SI{45}{\%}&\SI{13793.45}{\sieuro}\\
2 &\textbf{Werkzeugsatz} (G7111B\#001)\newline HPLC System Tool Kit, für Agilent 1260/1290 Infinity II LC.\newline Listenpreis: \SI{400}{\sieuro}&1&\SI{45}{\%}&\SI{220}{\sieuro}\\
3 &\textbf{Aktive Kolbenhinterspülung} (G7111B\#030)\newline Automatische Reinigung und Pflege der Pumpenköpfe, -dichtungen und -ventile für maximale Lebensdauer. Besonders empfohlen bei salzhaltigen Analyten oder Puffern.\newline Listenpreis: \SI{1463}{\sieuro}&1&\SI{45}{\%}&\SI{804.65}{\sieuro}\\
4 &\textbf{Aktives Einlassventil} (G7111B\#032)\newline Aktives Einlassventil (AIV) für einen zuverlässigen Pumpenbetrieb bei der Verwendung von Puffern.\newline Listenpreis: \SI{889}{\sieuro}&1&\SI{45}{\%}&\SI{488.95}{\sieuro}\\
5 &\textbf{Säule} (G7111B\#094)\newline InfinityLab Poroshell 120 EC-C18, 3.0 x 150 mm, 2.7 µm.\newline Listenpreis: \SI{1}{\sieuro}&1&\SI{45}{\%}&\SI{0.55}{\sieuro}\\
6 &\textbf{Vialsampler} (G7129A)\newline 1260 Infinity II automatischer Flüssigprobengeber zur Verwendung bei bis zu 600 bar. Mit integriertem Nadelspülanschluss zur Minimierung der Verschleppung, 100 µl Dosiereinheit und 100 µl Probenschleife. Inklusive Gerätetreiber für ein LC-System (2D-UV).\newline Listenpreis: \SI{19905}{\sieuro}&1&\SI{45}{\%}&\SI{10947.75}{\sieuro}\\
7 &\textbf{Probenteller für 6x11 2,0 ml Vials} (G7129A\#010)\newline \newline Listenpreis: \SI{375}{\sieuro}&1&\SI{45}{\%}&\SI{206.25}{\sieuro}\\
8 &\textbf{Ohne Gerätetreiber} (G7129A\#060)\newline Es wird ein vorhandener Gerätetreiber verwendet oder mit der Software angeboten.\newline Listenpreis: \SI{-1793}{\sieuro}&1&\SI{45}{\%}&\SI{-986.15}{\sieuro}\\
9 &\textbf{Säulenthermostat} (G7116A)\newline 1260 Infinity II Thermostat für bis zu vier 30 cm Säulen, Temperaturbereich: 10° unter Raumtemperatur (min. 4 °C) bis max. 85 °C, inkl. Säulenidentifikations-Kit. Ventilantrieb optional.\newline Listenpreis: \SI{6494}{\sieuro}&1&\SI{45}{\%}&\SI{3571.7}{\sieuro}\\
10 &\textbf{Ventilantrieb} (G7116A\#058)\newline Ventilantrieb für 1260 Infinity II Thermostat G7116A. Zur Verwendung mit QuickChange-Ventilköpfen.\newline Listenpreis: \SI{1541}{\sieuro}&1&\SI{45}{\%}&\SI{847.55}{\sieuro}\\
11 &\textbf{4-Säulenauswahlventil} (G4237A)\newline QuickChange-Ventilkopf zur Auswahl von 4 Säulen (4Pos./10 Anschlüsse), max. 800 bar. Zum schnellen Säulenwechsel oder Schaltung eines Bypasses zur Direktaufgabe auf das Massenspektrometer.\newline Listenpreis: \SI{4808}{\sieuro}&1&\SI{45}{\%}&\SI{2644.4}{\sieuro}\\
12 &\textbf{Kapillarkit} (G4237A\#006)\newline 4-Säulenauswahlventil-Kapillarkit, Inhalt: 0,17 mm ID Kapillaren und vier Quick Connect-Wärmetauscher, zur Verwendung in G7116A.\newline Listenpreis: \SI{3474}{\sieuro}&1&\SI{45}{\%}&\SI{1910.7}{\sieuro}\\
13 &\textbf{Diodenarraydetektor HS} (G7117C)\newline 1260 Infinity II Diodenarray-Detektor high sensitivity für höchste Empfindlichkeit, 120 Hz Datenrate für schnelle Multiwellenlängen- und Spektralanalysen. Messbereich 190 640 nm, RFID-Tags für Zelle und Lampe. Inklusive Standard-Max-Light-Flusszelle (10 mm, V = 1 µl, max. 70 bar).\newline Listenpreis: \SI{24906}{\sieuro}&1&\SI{45}{\%}&\SI{13698.3}{\sieuro}\\
14 &\textbf{Fluoreszenzspektrendetektor} (G7121B)\newline 1260 Infinity II Fluoreszenzdetektor, spektrenfähig.\newline Für Multiwellenlängen-Detektion, Online-Aufnahme von  Anregungs- und Emissionsspektren (200 1200 nm), Datenrate bis 148 Hz. Inkl. Standard-Durchflusszelle (V = 8 µl, max. 20 bar).\newline Listenpreis: \SI{21984}{\sieuro}&1&\SI{45}{\%}&\SI{12091.2}{\sieuro}\\
15 &\textbf{OpenLab CDS 2 Instrument Connection} (M8431AA)\newline \newline Listenpreis: \SI{1364}{\sieuro}&1&\SI{45}{\%}&\SI{750.2}{\sieuro}\\
16 &\textbf{OpenLab CDS 2 IC für LC} (M8431AA\#001)\newline Lizenz und Treiber zur Gerätesteuerung unter OpenLab CDS. Gerätetyp: LC (ohne DAD)\newline Listenpreis: \SI{0}{\sieuro}&1&\SI{45}{\%}&\SI{0}{\sieuro}\\
17 &\textbf{OpenLab CDS 2 IC für 3D-UV/DAD} (M8431AA\#005)\newline Lizenz und Treiber zur Gerätesteuerung unter OpenLab CDS. Gerätetyp: 3D-UV/DAD\newline Listenpreis: \SI{0}{\sieuro}&1&\SI{45}{\%}&\SI{0}{\sieuro}\\
18 &\textbf{1260 Infinity II HPLC mit Zusatzfunktionen} (SYS-LC-1260IIE)\newline \newline Listenpreis: \SI{0}{\sieuro}&1&\SI{20}{\%}&\SI{0}{\sieuro}\\
19 &\textbf{Einführung} (SYS-LC-1260IIE\#2A9)\newline Standardeinweisung für neue Anwender im Rahmen der Installation.\newline Listenpreis: \SI{1193}{\sieuro}&1&\SI{20}{\%}&\SI{954.4}{\sieuro}\\
20 &\textbf{Erweiterte Gewährleistung für akademische Kunden, zwei Jahre komplett} (SYS-LC-1260IIE\#9EC)\newline Verlängerung der Gewährleistung von 12 auf 24 Monate.\newline Listenpreis: \SI{5215}{\sieuro}&1&\SI{40}{\%}&\SI{3129}{\sieuro}\\
21 &\textbf{Überprüfung, Deinstallation und Versand} (R2005A)\newline Überprüfung, Deinstallation und Versand der in Zahlung gegebenen Geräte.\newline Die erfolgreiche Überprüfung der Geräte durch einen Agilent Techniker ist Voraussetzung für die Annahme der Inzahlungnahme durch Agilent.\newline Listenpreis: \SI{0}{\sieuro}&1&\SI{0}{\%}&\SI{0}{\sieuro}\\
\hline
\end{longtable}
\end{center}
\vspace{-2cm}
\begin{flushright}
\begin{tabular}{|rr|}
\hline
\textbf{Summe netto} & \SI{65072.90}{\sieuro}\\
\textbf{Versand und Bereitstellungskosten (3\%)} & \SI{1952.187}{\sieuro}\\
\textbf{Gesamtsumme netto} & \SI{67025.087}{\sieuro}\\
\textbf{Umsatzsteuer (19\%)} & \SI{12734.76653}{\sieuro}\\
\textbf{Gesamtsumme brutto} & \SI{79759.85353}{\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 24 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}

@ -0,0 +1,22 @@
# 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 G7111B 29 1260 Infinity II quaternaere Pumpe 1 25079 0 0 45 13793.45 13793.45 25 20 0 0 ISL100P1 Pumps
2 G7111B 001 29 HPLC System Tool Kit 1260 Infinity II 1 400 0 0 45 220 220 25 20 0 0
3 G7111B 030 29 Aktive Kolbenhinterspuelung 1 1463 0 0 45 804.65 804.65 25 20 0 0
4 G7111B 032 29 Aktiveinlassventil (AIV) 1 889 0 0 45 488.95 488.95 25 20 0 0
5 G7111B 094 29 Poroshell 120 EC-C18 3,0x150mm, 2,7um 1 1 0 0 45 0.55 0.55 25 20 0 0
6 G7129A 29 1260 Inf. II Fluessigprobengeber 1 19905 0 0 45 10947.75 10947.75 25 20 0 0 ISL100A1 Autosamplers
7 G7129A 010 29 Standard-Schublade (6x11 Probenflaschen) 1 375 0 0 45 206.25 206.25 25 20 0 0
8 G7129A 060 29 Nutzung vorhandene Lizenz 1 -1793 0 0 45 -986.15 -986.15 25 20 0 0
9 G7116A 29 1260 Infinity II Therm. f. mehr. Saeulen 1 6494 0 0 45 3571.7 3571.7 25 20 0 0 ISL100LC1 LC Hardware
10 G7116A 058 29 Ventilantrieb fuer 1260 Infinity II MCT 1 1541 0 0 45 847.55 847.55 25 20 0 0
11 G4237A 29 4Pos./10Anschl., 4-Saeulenausw. 800 bar 1 4808 0 0 45 2644.4 2644.4 25 20 0 0 ISL100LCV LC Valves
12 G4237A 006 29 Kapillarkit 0,17 mm, 4-Saeulen, m. QC-HE 1 3474 0 0 45 1910.7 1910.7 25 20 0 0
13 G7117C 29 1260 Infinity II Diodenarray-Detektor HS 1 24906 0 0 45 13698.3 13698.3 25 20 0 0 ISL100D1 Detectors
14 G7121B 29 1260 Infinity II FLD Spektren 1 21984 0 0 45 12091.2 12091.2 25 20 0 0 ISL100D1 Detectors
15 M8431AA LI OpenLab CDS Geraeteverbindung 1 1364 0 0 45 750.2 750.2 25 20 0 0 ISF300F100 OpenLAB CDS Software
16 M8431AA 001 LI LC-Geraeteverbindung 1 0 0 0 45 0 0 25 20 0 0
17 M8431AA 005 LI 3D UV/DAD-Verb. 1 0 0 0 45 0 0 25 20 0 0
18 SYS-LC-1260IIE 74 LC 1260 Infinity II System m. Zusatzfkt. 1 0 0 0 20 0 0 20 0 0 0 TSSYS0SYLC Service Systems - Liquid Chromatography
19 SYS-LC-1260IIE 2A9 74 Standard-Einweisung 1 1193 0 0 20 954.4 954.4 20 0 0 0 TSSTRN Training Services
20 SYS-LC-1260IIE 9EC 74 Erweit. Gewaehr. fuer Akad. - 2J, kompl. 1 5215 0 0 40 3129 3129 40 0 0 0 TSSYSX Academic Extended Warranty
21 R2005A RB Eingetauschte Geraete Deinst. und Vers. 1 0 0 0 0 0 0 0 0 0 0
1 # 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
2 1 G7111B 29 1260 Infinity II quaternaere Pumpe 1 25079 0 0 45 13793.45 13793.45 25 20 0 0 ISL100P1 Pumps
3 2 G7111B 001 29 HPLC System Tool Kit 1260 Infinity II 1 400 0 0 45 220 220 25 20 0 0
4 3 G7111B 030 29 Aktive Kolbenhinterspuelung 1 1463 0 0 45 804.65 804.65 25 20 0 0
5 4 G7111B 032 29 Aktiveinlassventil (AIV) 1 889 0 0 45 488.95 488.95 25 20 0 0
6 5 G7111B 094 29 Poroshell 120 EC-C18 3,0x150mm, 2,7um 1 1 0 0 45 0.55 0.55 25 20 0 0
7 6 G7129A 29 1260 Inf. II Fluessigprobengeber 1 19905 0 0 45 10947.75 10947.75 25 20 0 0 ISL100A1 Autosamplers
8 7 G7129A 010 29 Standard-Schublade (6x11 Probenflaschen) 1 375 0 0 45 206.25 206.25 25 20 0 0
9 8 G7129A 060 29 Nutzung vorhandene Lizenz 1 -1793 0 0 45 -986.15 -986.15 25 20 0 0
10 9 G7116A 29 1260 Infinity II Therm. f. mehr. Saeulen 1 6494 0 0 45 3571.7 3571.7 25 20 0 0 ISL100LC1 LC Hardware
11 10 G7116A 058 29 Ventilantrieb fuer 1260 Infinity II MCT 1 1541 0 0 45 847.55 847.55 25 20 0 0
12 11 G4237A 29 4Pos./10Anschl., 4-Saeulenausw. 800 bar 1 4808 0 0 45 2644.4 2644.4 25 20 0 0 ISL100LCV LC Valves
13 12 G4237A 006 29 Kapillarkit 0,17 mm, 4-Saeulen, m. QC-HE 1 3474 0 0 45 1910.7 1910.7 25 20 0 0
14 13 G7117C 29 1260 Infinity II Diodenarray-Detektor HS 1 24906 0 0 45 13698.3 13698.3 25 20 0 0 ISL100D1 Detectors
15 14 G7121B 29 1260 Infinity II FLD Spektren 1 21984 0 0 45 12091.2 12091.2 25 20 0 0 ISL100D1 Detectors
16 15 M8431AA LI OpenLab CDS Geraeteverbindung 1 1364 0 0 45 750.2 750.2 25 20 0 0 ISF300F100 OpenLAB CDS Software
17 16 M8431AA 001 LI LC-Geraeteverbindung 1 0 0 0 45 0 0 25 20 0 0
18 17 M8431AA 005 LI 3D UV/DAD-Verb. 1 0 0 0 45 0 0 25 20 0 0
19 18 SYS-LC-1260IIE 74 LC 1260 Infinity II System m. Zusatzfkt. 1 0 0 0 20 0 0 20 0 0 0 TSSYS0SYLC Service Systems - Liquid Chromatography
20 19 SYS-LC-1260IIE 2A9 74 Standard-Einweisung 1 1193 0 0 20 954.4 954.4 20 0 0 0 TSSTRN Training Services
21 20 SYS-LC-1260IIE 9EC 74 Erweit. Gewaehr. fuer Akad. - 2J, kompl. 1 5215 0 0 40 3129 3129 40 0 0 0 TSSYSX Academic Extended Warranty
22 21 R2005A RB Eingetauschte Geraete Deinst. und Vers. 1 0 0 0 0 0 0 0 0 0 0

@ -0,0 +1,177 @@
\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-423-223}
\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-423-223\\
Angebotdatum:&\today\\
Angebotsgültigkeit:&60 Tage\\\textbf{Ansprechpartner:}&Sascha Woitschetzki\\
Telefon: &+49 176 22285334\\
Mobil:&\\
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 Karl De Jong
\\
Stadtwerke Aachen AG Strom-Gas-Wasser-Wärme
\\
Lombardenstr 12-22
\\
52070 Aachen
\\
&\\
&\\
\end{tabular}
\vspace{1cm}\par
Sehr geehrter Herr De Jong,\par
nachfolgend erhalten Sie Ihr gewünschtes Angebot über ein(e) Gerät.\\
Es umfasst im Einzelnen:
\begin{itemize}
\item quaternäre Pumpe mit integriertem Entgaser (\#1)
\begin{itemize}
\item Werkzeugsatz (\#2)
\item Aktive Kolbenhinterspülung (\#3)
\item Aktives Einlassventil (\#4)
\item Säule (\#5)
\end{itemize}
\item Vialsampler (\#6)
\begin{itemize}
\item Probenteller für 6x11 2,0 ml Vials (\#7)
\item Ohne Gerätetreiber (\#8)
\end{itemize}
\item Säulenthermostat (\#9)
\begin{itemize}
\item Ventilantrieb (\#10)
\end{itemize}
\item 4-Säulenauswahlventil (\#11)
\begin{itemize}
\item Kapillarkit (\#12)
\end{itemize}
\item Diodenarraydetektor High Sensitivity (\#13)
\item Fluoreszenzspektrendetektor (\#14)
\item OpenLab CDS 2 Instrument Connection (\#15)
\begin{itemize}
\item OpenLab CDS 2 IC für LC (\#16)
\item OpenLab CDS 2 IC für 3D-UV/DAD (\#17)
\end{itemize}
\item 1260 Infinity II HPLC mit Zusatzfunktionen (\#18)
\begin{itemize}
\item Einführung (\#19)
\item Zwei Jahre Gewährleistung (\#20)
\end{itemize}
\item Überprüfung, Deinstallation und Versand (\#21)
\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{Quaternäre Pumpe} (G7111B)\newline 1260 Infinity II quaternäre Pumpe, Maximaldruck 600 bar. Mit integriertem 4-Kanal-Entgaser, vergünstigter Säule, Verbindungskapillaren, Lösemittelwanne und -flaschen.\newline Listenpreis: \SI{25079}{\sieuro}&1&\SI{45}{\%}&\SI{13793.45}{\sieuro}\\
2 &\textbf{Werkzeugsatz} (G7111B\#001)\newline HPLC System Tool Kit, für Agilent 1260/1290 Infinity II LC.\newline Listenpreis: \SI{400}{\sieuro}&1&\SI{45}{\%}&\SI{220}{\sieuro}\\
3 &\textbf{Aktive Kolbenhinterspülung} (G7111B\#030)\newline Automatische Reinigung und Pflege der Pumpenköpfe, -dichtungen und -ventile für maximale Lebensdauer. Besonders empfohlen bei salzhaltigen Analyten oder Puffern.\newline Listenpreis: \SI{1463}{\sieuro}&1&\SI{45}{\%}&\SI{804.65}{\sieuro}\\
4 &\textbf{Aktives Einlassventil} (G7111B\#032)\newline Aktives Einlassventil (AIV) für einen zuverlässigen Pumpenbetrieb bei der Verwendung von Puffern.\newline Listenpreis: \SI{889}{\sieuro}&1&\SI{45}{\%}&\SI{488.95}{\sieuro}\\
5 &\textbf{Säule} (G7111B\#094)\newline InfinityLab Poroshell 120 EC-C18, 3.0 x 150 mm, 2.7 µm.\newline Listenpreis: \SI{1}{\sieuro}&1&\SI{45}{\%}&\SI{0.55}{\sieuro}\\
6 &\textbf{Vialsampler} (G7129A)\newline 1260 Infinity II automatischer Flüssigprobengeber zur Verwendung bei bis zu 600 bar. Mit integriertem Nadelspülanschluss zur Minimierung der Verschleppung, 100 µl Dosiereinheit und 100 µl Probenschleife. Inklusive Gerätetreiber für ein LC-System (2D-UV).\newline Listenpreis: \SI{19905}{\sieuro}&1&\SI{45}{\%}&\SI{10947.75}{\sieuro}\\
7 &\textbf{Probenteller für 6x11 2,0 ml Vials} (G7129A\#010)\newline \newline Listenpreis: \SI{375}{\sieuro}&1&\SI{45}{\%}&\SI{206.25}{\sieuro}\\
8 &\textbf{Ohne Gerätetreiber} (G7129A\#060)\newline Es wird ein vorhandener Gerätetreiber verwendet oder mit der Software angeboten.\newline Listenpreis: \SI{-1793}{\sieuro}&1&\SI{45}{\%}&\SI{-986.15}{\sieuro}\\
9 &\textbf{Säulenthermostat} (G7116A)\newline 1260 Infinity II Thermostat für bis zu vier 30 cm Säulen, Temperaturbereich: 10° unter Raumtemperatur (min. 4 °C) bis max. 85 °C, inkl. Säulenidentifikations-Kit. Ventilantrieb optional.\newline Listenpreis: \SI{6494}{\sieuro}&1&\SI{45}{\%}&\SI{3571.7}{\sieuro}\\
10 &\textbf{Ventilantrieb} (G7116A\#058)\newline Ventilantrieb für 1260 Infinity II Thermostat G7116A. Zur Verwendung mit QuickChange-Ventilköpfen.\newline Listenpreis: \SI{1541}{\sieuro}&1&\SI{45}{\%}&\SI{847.55}{\sieuro}\\
11 &\textbf{4-Säulenauswahlventil} (G4237A)\newline QuickChange-Ventilkopf zur Auswahl von 4 Säulen (4Pos./10 Anschlüsse), max. 800 bar. Zum schnellen Säulenwechsel oder Schaltung eines Bypasses zur Direktaufgabe auf das Massenspektrometer.\newline Listenpreis: \SI{4808}{\sieuro}&1&\SI{45}{\%}&\SI{2644.4}{\sieuro}\\
12 &\textbf{Kapillarkit} (G4237A\#006)\newline 4-Säulenauswahlventil-Kapillarkit, Inhalt: 0,17 mm ID Kapillaren und vier Quick Connect-Wärmetauscher, zur Verwendung in G7116A.\newline Listenpreis: \SI{3474}{\sieuro}&1&\SI{45}{\%}&\SI{1910.7}{\sieuro}\\
13 &\textbf{Diodenarraydetektor HS} (G7117C)\newline 1260 Infinity II Diodenarray-Detektor high sensitivity für höchste Empfindlichkeit, 120 Hz Datenrate für schnelle Multiwellenlängen- und Spektralanalysen. Messbereich 190 640 nm, RFID-Tags für Zelle und Lampe. Inklusive Standard-Max-Light-Flusszelle (10 mm, V = 1 µl, max. 70 bar).\newline Listenpreis: \SI{24906}{\sieuro}&1&\SI{45}{\%}&\SI{13698.3}{\sieuro}\\
14 &\textbf{Fluoreszenzspektrendetektor} (G7121B)\newline 1260 Infinity II Fluoreszenzdetektor, spektrenfähig.\newline Für Multiwellenlängen-Detektion, Online-Aufnahme von  Anregungs- und Emissionsspektren (200 1200 nm), Datenrate bis 148 Hz. Inkl. Standard-Durchflusszelle (V = 8 µl, max. 20 bar).\newline Listenpreis: \SI{21984}{\sieuro}&1&\SI{45}{\%}&\SI{12091.2}{\sieuro}\\
15 &\textbf{OpenLab CDS 2 Instrument Connection} (M8431AA)\newline \newline Listenpreis: \SI{1364}{\sieuro}&1&\SI{45}{\%}&\SI{750.2}{\sieuro}\\
16 &\textbf{OpenLab CDS 2 IC für LC} (M8431AA\#001)\newline Lizenz und Treiber zur Gerätesteuerung unter OpenLab CDS. Gerätetyp: LC (ohne DAD)\newline Listenpreis: \SI{0}{\sieuro}&1&\SI{45}{\%}&\SI{0}{\sieuro}\\
17 &\textbf{OpenLab CDS 2 IC für 3D-UV/DAD} (M8431AA\#005)\newline Lizenz und Treiber zur Gerätesteuerung unter OpenLab CDS. Gerätetyp: 3D-UV/DAD\newline Listenpreis: \SI{0}{\sieuro}&1&\SI{45}{\%}&\SI{0}{\sieuro}\\
18 &\textbf{1260 Infinity II HPLC mit Zusatzfunktionen} (SYS-LC-1260IIE)\newline \newline Listenpreis: \SI{0}{\sieuro}&1&\SI{20}{\%}&\SI{0}{\sieuro}\\
19 &\textbf{Einführung} (SYS-LC-1260IIE\#2A9)\newline Standardeinweisung für neue Anwender im Rahmen der Installation.\newline Listenpreis: \SI{1193}{\sieuro}&1&\SI{20}{\%}&\SI{954.4}{\sieuro}\\
20 &\textbf{Erweiterte Gewährleistung für akademische Kunden, zwei Jahre komplett} (SYS-LC-1260IIE\#9EC)\newline Verlängerung der Gewährleistung von 12 auf 24 Monate.\newline Listenpreis: \SI{5215}{\sieuro}&1&\SI{40}{\%}&\SI{3129}{\sieuro}\\
21 &\textbf{Überprüfung, Deinstallation und Versand} (R2005A)\newline Überprüfung, Deinstallation und Versand der in Zahlung gegebenen Geräte.\newline Die erfolgreiche Überprüfung der Geräte durch einen Agilent Techniker ist Voraussetzung für die Annahme der Inzahlungnahme durch Agilent.\newline Listenpreis: \SI{0}{\sieuro}&1&\SI{0}{\%}&\SI{0}{\sieuro}\\
\hline
\end{longtable}
\end{center}
\vspace{-2cm}
\begin{flushright}
\begin{tabular}{|rr|}
\hline
\textbf{Summe netto} & \SI{65072.90}{\sieuro}\\
\textbf{Versand und Bereitstellungskosten (3\%)} & \SI{1952.187}{\sieuro}\\
\textbf{Gesamtsumme netto} & \SI{67025.087}{\sieuro}\\
\textbf{Umsatzsteuer (19\%)} & \SI{12734.76653}{\sieuro}\\
\textbf{Gesamtsumme brutto} & \SI{79759.85353}{\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 24 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}

@ -0,0 +1,22 @@
# 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 G7111B 29 1260 Infinity II quaternaere Pumpe 1 25079 0 0 45 13793.45 13793.45 25 20 0 0 ISL100P1 Pumps
2 G7111B 001 29 HPLC System Tool Kit 1260 Infinity II 1 400 0 0 45 220 220 25 20 0 0
3 G7111B 030 29 Aktive Kolbenhinterspuelung 1 1463 0 0 45 804.65 804.65 25 20 0 0
4 G7111B 032 29 Aktiveinlassventil (AIV) 1 889 0 0 45 488.95 488.95 25 20 0 0
5 G7111B 094 29 Poroshell 120 EC-C18 3,0x150mm, 2,7um 1 1 0 0 45 0.55 0.55 25 20 0 0
6 G7129A 29 1260 Inf. II Fluessigprobengeber 1 19905 0 0 45 10947.75 10947.75 25 20 0 0 ISL100A1 Autosamplers
7 G7129A 010 29 Standard-Schublade (6x11 Probenflaschen) 1 375 0 0 45 206.25 206.25 25 20 0 0
8 G7129A 060 29 Nutzung vorhandene Lizenz 1 -1793 0 0 45 -986.15 -986.15 25 20 0 0
9 G7116A 29 1260 Infinity II Therm. f. mehr. Saeulen 1 6494 0 0 45 3571.7 3571.7 25 20 0 0 ISL100LC1 LC Hardware
10 G7116A 058 29 Ventilantrieb fuer 1260 Infinity II MCT 1 1541 0 0 45 847.55 847.55 25 20 0 0
11 G4237A 29 4Pos./10Anschl., 4-Saeulenausw. 800 bar 1 4808 0 0 45 2644.4 2644.4 25 20 0 0 ISL100LCV LC Valves
12 G4237A 006 29 Kapillarkit 0,17 mm, 4-Saeulen, m. QC-HE 1 3474 0 0 45 1910.7 1910.7 25 20 0 0
13 G7117C 29 1260 Infinity II Diodenarray-Detektor HS 1 24906 0 0 45 13698.3 13698.3 25 20 0 0 ISL100D1 Detectors
14 G7121B 29 1260 Infinity II FLD Spektren 1 21984 0 0 45 12091.2 12091.2 25 20 0 0 ISL100D1 Detectors
15 M8431AA LI OpenLab CDS Geraeteverbindung 1 1364 0 0 45 750.2 750.2 25 20 0 0 ISF300F100 OpenLAB CDS Software
16 M8431AA 001 LI LC-Geraeteverbindung 1 0 0 0 45 0 0 25 20 0 0
17 M8431AA 005 LI 3D UV/DAD-Verb. 1 0 0 0 45 0 0 25 20 0 0
18 SYS-LC-1260IIE 74 LC 1260 Infinity II System m. Zusatzfkt. 1 0 0 0 20 0 0 20 0 0 0 TSSYS0SYLC Service Systems - Liquid Chromatography
19 SYS-LC-1260IIE 2A9 74 Standard-Einweisung 1 1193 0 0 20 954.4 954.4 20 0 0 0 TSSTRN Training Services
20 SYS-LC-1260IIE 9EC 74 Erweit. Gewaehr. fuer Akad. - 2J, kompl. 1 5215 0 0 40 3129 3129 40 0 0 0 TSSYSX Academic Extended Warranty
21 R2005A RB Eingetauschte Geraete Deinst. und Vers. 1 0 0 0 0 0 0 0 0 0 0
1 # 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
2 1 G7111B 29 1260 Infinity II quaternaere Pumpe 1 25079 0 0 45 13793.45 13793.45 25 20 0 0 ISL100P1 Pumps
3 2 G7111B 001 29 HPLC System Tool Kit 1260 Infinity II 1 400 0 0 45 220 220 25 20 0 0
4 3 G7111B 030 29 Aktive Kolbenhinterspuelung 1 1463 0 0 45 804.65 804.65 25 20 0 0
5 4 G7111B 032 29 Aktiveinlassventil (AIV) 1 889 0 0 45 488.95 488.95 25 20 0 0
6 5 G7111B 094 29 Poroshell 120 EC-C18 3,0x150mm, 2,7um 1 1 0 0 45 0.55 0.55 25 20 0 0
7 6 G7129A 29 1260 Inf. II Fluessigprobengeber 1 19905 0 0 45 10947.75 10947.75 25 20 0 0 ISL100A1 Autosamplers
8 7 G7129A 010 29 Standard-Schublade (6x11 Probenflaschen) 1 375 0 0 45 206.25 206.25 25 20 0 0
9 8 G7129A 060 29 Nutzung vorhandene Lizenz 1 -1793 0 0 45 -986.15 -986.15 25 20 0 0
10 9 G7116A 29 1260 Infinity II Therm. f. mehr. Saeulen 1 6494 0 0 45 3571.7 3571.7 25 20 0 0 ISL100LC1 LC Hardware
11 10 G7116A 058 29 Ventilantrieb fuer 1260 Infinity II MCT 1 1541 0 0 45 847.55 847.55 25 20 0 0
12 11 G4237A 29 4Pos./10Anschl., 4-Saeulenausw. 800 bar 1 4808 0 0 45 2644.4 2644.4 25 20 0 0 ISL100LCV LC Valves
13 12 G4237A 006 29 Kapillarkit 0,17 mm, 4-Saeulen, m. QC-HE 1 3474 0 0 45 1910.7 1910.7 25 20 0 0
14 13 G7117C 29 1260 Infinity II Diodenarray-Detektor HS 1 24906 0 0 45 13698.3 13698.3 25 20 0 0 ISL100D1 Detectors
15 14 G7121B 29 1260 Infinity II FLD Spektren 1 21984 0 0 45 12091.2 12091.2 25 20 0 0 ISL100D1 Detectors
16 15 M8431AA LI OpenLab CDS Geraeteverbindung 1 1364 0 0 45 750.2 750.2 25 20 0 0 ISF300F100 OpenLAB CDS Software
17 16 M8431AA 001 LI LC-Geraeteverbindung 1 0 0 0 45 0 0 25 20 0 0
18 17 M8431AA 005 LI 3D UV/DAD-Verb. 1 0 0 0 45 0 0 25 20 0 0
19 18 SYS-LC-1260IIE 74 LC 1260 Infinity II System m. Zusatzfkt. 1 0 0 0 20 0 0 20 0 0 0 TSSYS0SYLC Service Systems - Liquid Chromatography
20 19 SYS-LC-1260IIE 2A9 74 Standard-Einweisung 1 1193 0 0 20 954.4 954.4 20 0 0 0 TSSTRN Training Services
21 20 SYS-LC-1260IIE 9EC 74 Erweit. Gewaehr. fuer Akad. - 2J, kompl. 1 5215 0 0 40 3129 3129 40 0 0 0 TSSYSX Academic Extended Warranty
22 21 R2005A RB Eingetauschte Geraete Deinst. und Vers. 1 0 0 0 0 0 0 0 0 0 0