Import of Custom Descriptions

pull/3/head
Sascha 2023-08-23 10:27:29 +07:00
parent f2deb16b3d
commit 2b695a3ce4
17 changed files with 269 additions and 38 deletions

@ -10,7 +10,6 @@ using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.WebUtilities;

@ -7,7 +7,6 @@ using System.ComponentModel.DataAnnotations;
using System.Text;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.WebUtilities;

@ -0,0 +1,5 @@
namespace Gremlin_BlazorServer.Areas.Identity.Pages.Account;
public interface IEmailSender {
Task SendEmailAsync(string email, string subject, string htmlMessage);
}

@ -7,7 +7,6 @@ using System.ComponentModel.DataAnnotations;
using System.Text;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.WebUtilities;

@ -8,7 +8,6 @@ using System.Text;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.WebUtilities;

@ -6,7 +6,6 @@
using System.Text;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.WebUtilities;

@ -8,7 +8,6 @@ using System.Text;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.WebUtilities;

@ -1,6 +1,4 @@
using Newtonsoft.Json;
namespace Gremlin_BlazorServer.Data.EntityClasses;
namespace Gremlin_BlazorServer.Data.EntityClasses;
public class Contact : IMetadata {
//primary key:

@ -34,4 +34,30 @@ public class CustomDescription : IMetadata {
public uint DataVersionNumber { get; set; }
public string? DataVersionComment { get; set; }
public string DataStatus { get; set; } = "Active";
public bool Equals(CustomDescription? other) {
if (other is null) return false;
return ProductNumber == other.ProductNumber && OptionNumber == other.OptionNumber && Heading == other.Heading &&
DescriptionText == other.DescriptionText && CoverletterText == other.CoverletterText;
}
public static bool operator ==(CustomDescription? customDescription1, CustomDescription? customDescription2) {
if (customDescription1 is null || customDescription2 is null) return false;
return customDescription1.ProductNumber == customDescription2.ProductNumber &&
customDescription1.OptionNumber == customDescription2.OptionNumber &&
customDescription1.Heading == customDescription2.Heading &&
customDescription1.DescriptionText == customDescription2.DescriptionText &&
customDescription1.CoverletterText == customDescription2.CoverletterText;
}
public static bool operator !=(CustomDescription? customDescription1, CustomDescription? customDescription2)
{
if (customDescription1 is null || customDescription2 is null) return false;
return customDescription1.ProductNumber != customDescription2.ProductNumber &&
customDescription1.OptionNumber != customDescription2.OptionNumber &&
customDescription1.Heading != customDescription2.Heading &&
customDescription1.DescriptionText != customDescription2.DescriptionText &&
customDescription1.CoverletterText != customDescription2.CoverletterText &&
customDescription1.Notes != customDescription2.Notes;
}
}

@ -71,13 +71,16 @@
Padding="Padding.Is3"
style="box-shadow: 10px 10px #343A40">
<Heading Size="HeadingSize.Is4">Import</Heading>
<Paragraph>
<Field>
<FieldLabel>Import CustomDescriptions</FieldLabel>
<FileEdit Filter=".csv" Changed="@OnImportCustomDescriptions"/>
</Field>
</Paragraph>
<Paragraph>
<Button Color="Color.Primary" Clicked="@OnRemoveDublicates">Remove Dublicates</Button>
</Paragraph>
<Heading Size="HeadingSize.Is6">Import Products from CSV</Heading>
<Paragraph>
<Field>
<FileEdit Filter=".csv" Changed="@OnImportCustomDescriptions"/>
</Field>
</Paragraph>
</Div>
</Authorized>

@ -1,4 +1,3 @@
using System.Diagnostics;
using System.Security.Claims;
using Blazorise;
using Blazorise.DataGrid;
@ -74,4 +73,9 @@ public partial class CustomDescriptions {
return newCustomDescription;
}
private static async Task OnRemoveDublicates() {
int i = await GenericController.RemoveDublicatesAsync<CustomDescription>();
Console.WriteLine($"Removed {i} dublicates from CustomDescriptions.");
}
}

@ -1,5 +1,4 @@
using System.Diagnostics;
using Gremlin_BlazorServer.Data.DBClasses;
using Gremlin_BlazorServer.Data.DBClasses;
using Gremlin_BlazorServer.Data.EntityClasses;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
@ -212,16 +211,16 @@ public class GenericController {
Console.WriteLine($"!!! HandleConcurrencyException: {ex.Message}");
foreach (EntityEntry entry in ex.Entries)
switch (entry.Entity) {
case Quote or CustomDescription or Account or Contact or Product: {
case Quote or CustomDescription or Account or Contact or Product or CustomDescription: {
PropertyValues proposedValues = entry.CurrentValues;
PropertyValues? databaseValues = entry.GetDatabaseValues();
foreach (IProperty property in proposedValues.Properties) {
object? proposedValue = proposedValues[property];
object? databaseValue = databaseValues[property];
// TODO: decide which value should be written to database
// proposedValues[property] = <>;
}
// PropertyValues? databaseValues = entry.GetDatabaseValues();
// foreach (IProperty property in proposedValues.Properties) {
// object? proposedValue = proposedValues[property];
// object? databaseValue = databaseValues[property];
// // TODO: decide which value should be written to database
// // proposedValues[property] = <>;
// }
// Refresh original values to bypass next concurrency check
entry.OriginalValues.SetValues(proposedValues);

@ -1,7 +1,4 @@
using Blazorise;
using Google.Protobuf.WellKnownTypes;
using Gremlin_BlazorServer.Data.EntityClasses;
using MySqlX.XDevAPI.Common;
using Gremlin_BlazorServer.Data.EntityClasses;
namespace Gremlin_BlazorServer.Services;
@ -9,15 +6,17 @@ public class GenericImporter {
public static async void ImportCsv<T>(string fileContent) where T : class, IMetadata, new() {
Console.WriteLine($"GENERIC IMPORTER: Importing {typeof(T)} from csv...");
List<string[]> splitLines = SplitLines(fileContent);
List<string[]> splitLines = SplitLines<T>(fileContent);
Console.WriteLine($"Found {splitLines.Count} potential {typeof(T)} in csv.");
int i = await ParseLinesToResultSet<T>(splitLines);
Console.WriteLine(i > 0 ? $"GENERIC IMPORTER: wrote {i} to db." : "GENERIC IMPORTER: Error by writing to db!");
}
private static List<string[]> SplitLines(string fileContent) {
private static List<string[]> SplitLines<T>(string fileContent) where T : class, IMetadata, new() {
IEnumerable<string> fileLines = fileContent.Split(Environment.NewLine.ToCharArray());
List<string[]> fileList = (from clipboardLine in fileLines where clipboardLine != "" select clipboardLine.Split('\t')).ToList();
char seperator = '\t';
if (typeof(T) == typeof(CustomDescription)) seperator = '|';
List<string[]> fileList = (from clipboardLine in fileLines where clipboardLine != "" select clipboardLine.Split(seperator)).ToList();
return fileList;
}
@ -58,8 +57,7 @@ public class GenericImporter {
Tuple<T?, T?>? resultSet = new(new(), new());
List<T> updatedItems = new();
List<T> newItems = new();
IList<T>? allItems = await GenericController.GetAllAsync<T>();
if (allItems is null) return 0;
IList<T> allItems = await GenericController.GetAllAsync<T>() ?? new List<T>();
int i = 0;
IEnumerable<string[]> lines = lineList.Select(strings => strings.Select(x => x.Replace("\"", string.Empty)).ToArray()).ToList();
@ -68,6 +66,7 @@ public class GenericImporter {
if (typeof(T) == typeof(Account)) resultSet = ParseToAccount(line, allItems as IList<Account>) as Tuple<T?, T?>;
if (typeof(T) == typeof(Contact)) resultSet = ParseToContact(line, allItems as IList<Contact>) as Tuple<T?, T?>;
if (typeof(T) == typeof(Product)) resultSet = ParseToProduct(line, allItems as IList<Product>) as Tuple<T?, T?>;
if (typeof(T) == typeof(CustomDescription)) resultSet = ParseToCustomDescription(line, allItems as IList<CustomDescription>) as Tuple<T?, T?>;
if (resultSet is null) continue;
if (resultSet.Item1 is not null) updatedItems.Add(resultSet.Item1);
@ -234,4 +233,44 @@ public class GenericImporter {
return new(updatedProduct, newProduct);
}
private static Tuple<CustomDescription?, CustomDescription?>? ParseToCustomDescription(IReadOnlyList<string> line, IEnumerable<CustomDescription> allCustomDescriptions) {
//Produktnummer|Option|Non Agilent Produkt|Überschrift|Produktbeschreibung|Anschreiben|Rang|Originalbeschreibung|Veraltete_Originalbeschreibung
CustomDescription? updatedCustomDescription = null;
CustomDescription? newCustomDescription = null;
if (line[0].Contains("Produktnummer")) return null; //HACK: skip first row if header
CustomDescription readCustomDescription = new(){
ProductNumber = line[0],
OptionNumber = line[1],
Heading = line[3],
DescriptionText = line[4],
CoverletterText = line[5],
DataModificationByUser = "Gremlin Generic Importer",
};
if (readCustomDescription.ProductNumber == "") return null; //Skip empty lines
CustomDescription? existingCustomDescription = allCustomDescriptions.FirstOrDefault(p => p.ProductNumber.Equals(readCustomDescription.ProductNumber) && p.OptionNumber.Equals(readCustomDescription.OptionNumber));
if (existingCustomDescription is not null) {
if (existingCustomDescription.Equals(readCustomDescription)) return null;
existingCustomDescription.DataModificationDate = DateTime.Now;
existingCustomDescription.DataVersionNumber++;
existingCustomDescription.DataModificationByUser = "Updated by Gremlin Generic Importer";
existingCustomDescription.ProductNumber = readCustomDescription.ProductNumber;
existingCustomDescription.OptionNumber = readCustomDescription.OptionNumber;
existingCustomDescription.Heading = readCustomDescription.Heading;
existingCustomDescription.DescriptionText = readCustomDescription.DescriptionText;
existingCustomDescription.CoverletterText = readCustomDescription.CoverletterText;
existingCustomDescription.Notes = readCustomDescription.Notes;
// Console.WriteLine($"Update in CustomDescription {existingCustomDescription.ProductNumber}#{existingCustomDescription.OptionNumber}:{existingCustomDescription.Heading}");
updatedCustomDescription = existingCustomDescription;
}
else {
// Console.WriteLine($"Product {readCustomDescription.ProductNumber}#{readCustomDescription.OptionNumber}:{readCustomDescription.Heading} ist neu!");
newCustomDescription = readCustomDescription;
}
return new(updatedCustomDescription, newCustomDescription);
}
}

@ -1,7 +1,6 @@
using System.Globalization;
using System.Text;
using Gremlin_BlazorServer.Data.EntityClasses;
using Gremlin_BlazorServer.Pages.Quotes;
using NuGet.Packaging;
namespace Gremlin_BlazorServer.Services;

@ -0,0 +1,151 @@
\documentclass[a4paper,ngerman,parskip,10pt]{scrlttr2}
\usepackage{lmodern}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{babel}
\usepackage[hidelinks]{hyperref}
\usepackage[left=2cm, right=2cm, top=2cm, bottom=2cm]{geometry}
\usepackage[table]{xcolor}
\usepackage[right]{{eurosym}}
\usepackage[locale=DE]{{siunitx}}
\usepackage{{scrlayer-scrpage}}
\usepackage{{lastpage}}
\usepackage{{graphicx}}
\usepackage{{multirow}}
\usepackage{{longtable}}
\usepackage{{enumitem}}
\usepackage{{fp, xstring, spreadtab, numprint}}
\DeclareSIUnit{{\sieuro}}{{\mbox{{\euro}}}}
\rohead{DE-83PE89-823-272}
\cfoot{Seite \thepage/\pageref{LastPage}}
\sisetup{round-integer-to-decimal,round-precision=2,round-mode=places}
\newcommand{\produkttitel}[1]{\textsc{#1}}
\renewcommand{\arraystretch}{1.2}
\definecolor{AgilentBlau}{HTML}{0085d5}
\setlist{noitemsep}
\begin{document}
\begin{tabular}{p{0.4\hsize}p{0.5\hsize}}
\multirow{4}{*}{\includegraphics[width=0.9\hsize]{agilentLogo.png}}
&\normalsize{Agilent Technologies Deutschland GmbH}\\
&\normalsize{Life Sciences \& Chemical Analysis}\\
&\normalsize{Hewlett-Packard-Str. 8}\\
&\normalsize{D-76337 Waldbronn}
\end{tabular}
\par
\begin{flushright}
\colorbox{AgilentBlau}{\textcolor{white}{\textsc{\Huge{Angebot}}}}
\end{flushright}
\begin{tabular}{p{0.4\hsize}p{0.6\hsize}}
&
\multirow{4}{*}{
\begin{tabular}{|ll|}
\hline
\textbf{Angebotsnummer:}&DE-83PE89-823-272\\
Angebotdatum:&\today\\
Angebotsgültigkeit:&60 Tage\\\textbf{Ansprechpartner:}&Sascha Woitschetzki\\
Telefon: &+49 208 74129134\\
Mobil:&+49 163 9681131\\
E-Mail:&\href{mailto:sascha.woitschetzki@non.agilent.com}{sascha.woitschetzki@non.agilent.com}\\
\textbf{Auftragsannahme:}&\href{mailto:salesservices\_germany@agilent.com}{salesservices\_germany@agilent.com}\\
\hline
\end{tabular}
}\\
Frau Ina Woitschetzki
\\
Handelsvertretung Sascha Woitschetzki
\\
Parsevalstr. 58
\\
45470 Mülheim an der Ruhr
\\
&\\
&\\
\end{tabular}
\vspace{1cm}\par
Sehr geehrte Frau Woitschetzki,\par
nachfolgend erhalten Sie Ihr gewünschtes Angebot über ein(e) GCMSD.\\
Es umfasst im Einzelnen:
\begin{itemize}
\item Autosampler mit 16 Probenplätzen (\#1)
\item Autosamplererweiterung auf 150 Probenplätze (\#2)
\item 8890 Gaschromatograph (\#3)
\begin{itemize}
\item Multimode-Einlass (\#4)
\item Anschluss für MSD (\#5)
\item Flammenionisationsdetektor (\#6)
\item Vorbereitete Gasanschlüsse (\#7)
\end{itemize}
\item DB-624UI (\#8)
\item DB-5MS UI (\#9)
\item 5977B MSD EI/CI (\#10)
\begin{itemize}
\item 8890GC Transferline (\#11)
\item Ölfreie Vorpumpe IDP3 (\#12)
\end{itemize}
\end{itemize}
Für Rückfragen und Änderungswünsche stehe ich Ihnen gerne zur Verfügung.\par
Mit freundlichen Grüßen\\
\includegraphics[width = 5cm]{signWoitschetzki.png}
\vspace{1cm} \\
\begin{center}
\begin{longtable}
{| cp{0.595\textwidth} crr |} \hline
\textbf{\#} & \textbf{Produktbeschreibung} (Produktnummer) & \textbf{Menge} & \textbf{Discount} & \textbf{Preis}\\ \hline \endhead
1 &\textbf{Automatischer Probengeber 7693A} (G4513A)\newline Zur Injektion flüssiger Proben, 16 Probenplätze, Befestigungsstift, Parkhalterung für den GC, 10 µl-Spritze und Lösemittelflaschen.\newline Listenpreis: \SI{9476}{\sieuro}&1&\SI{45}{\%}&\SI{5211,8}{\sieuro}\\
2 &\textbf{Autosampler-Erweiterung auf 150 Probenplätze} (G4514A)\newline Erweiterung für den 7693A Autosampler, 150 Probenplätze auf drei heraus¬nehm¬baren Probenträgern. Optional mit kühl-/heizbaren Probenträgern, Barcodeleser, Probenvorbereitungsplätze (Heizen, Mischen) und Sample Prep Software.\newline Listenpreis: \SI{11092}{\sieuro}&2&\SI{45}{\%}&\SI{12201,2}{\sieuro}\\
3 &\textbf{8890 Gaschromatograph} (G3540A)\newline Agilent 8890 GC\newline Ofen bis 450 °C, Kühlen von 450 auf 50 °C in unter 4 Min., bis zu 2 Inlets und 4 Detektoren. Elektronische Druck- und Flusskontrolle (EPC; 0-99 psi, 0.001 psi Genauigkeit), retention time locking (RTL).\newline Listenpreis: \SI{20258}{\sieuro}&1&\SI{45}{\%}&\SI{11141,9}{\sieuro}\\
4 &\textbf{Multimode-Einlass} (G3540A\#151)\newline Multimode Einlasssystem für Kapillarsäulen, temperaturprogrammierbar zur kontrollierten Verdampfung, kühlbar (Luft oder fl. N2), mit elektronischer Drucksteuerung (EPC), max. 100 psi. Ermöglicht max. Empfindlichkeit durch die Injektion großer Volumina (100+ µl), Ver¬ring¬er¬ung von Matrix¬effekten, thermischen Zersetzungen und Nadel-Diskriminierungs¬effekten. \newline Injektionsmodi: pulsed/unpulsed, split/splitlos, heiß/kalt, on-column, large volume, solvent vent, cold trapping.\newline Listenpreis: \SI{12221}{\sieuro}&2&\SI{45}{\%}&\SI{13443,1}{\sieuro}\\
5 &\textbf{Anschluss für MSD} (G3540A\#201)\newline Linksseitig, Frontposition.\newline Listenpreis: \SI{2494}{\sieuro}&1&\SI{45}{\%}&\SI{1371,7}{\sieuro}\\
6 &\textbf{Flammenionisationsdetektor} (G3540A\#211)\newline Flammenionisationsdetektor mit elektronischer Fluss- /Drucksteuerung zur digitalen Steuerung aller Detektorgase. Optimiert für Kapillarsäulen.\newline Listenpreis: \SI{5124}{\sieuro}&1&\SI{45}{\%}&\SI{2818,2}{\sieuro}\\
7 &\textbf{Vorbereitete Gasanschlüsse} (G3540A\#305)\newline Ab Werk vorkonfektionierte Gasanschlüsse an allen EPCs.\newline Listenpreis: \SI{569}{\sieuro}&1&\SI{45}{\%}&\SI{312,95}{\sieuro}\\
8 &\textbf{DB-624UI} (122-1334UI)\newline Kapillarsäule DB-624 Ultra Inert, Länge: 30 m, Innendurchmesser: 0,25 mm, Filmdicke: 1.40 µm.\newline Listenpreis: \SI{831}{\sieuro}&1&\SI{45}{\%}&\SI{457,05}{\sieuro}\\
9 &\textbf{DB-5MS UI} (122-5532UI)\newline Kapillarsäule DB-5MS Ultra Inert, Länge: 30 m, Innendurchmesser: 0,25 mm, Filmdicke: 0,25 µm.\newline Listenpreis: \SI{841}{\sieuro}&1&\SI{45}{\%}&\SI{462,55}{\sieuro}\\
10 &\textbf{5977B MSD EI/CI} (G7078BA)\newline 5977B Inert Plus Single Quad MSD Turbo EI-Paket mit Extractor EI-Ionenquelle, CI-Ionenquelle und Hochvakuumsonde.\newline Inkl. MassHunter-Software mit zweiter Datenanalyselizenz, Workstation-PC und Softwarewartungsvertrag.\newline Listenpreis: \SI{122552}{\sieuro}&1&\SI{45}{\%}&\SI{67403,6}{\sieuro}\\
11 &\textbf{8890GC Transferline} (G7078BA\#245)\newline GC/MSD EI/CI Mainframe für 8890GC\newline Listenpreis: \SI{0}{\sieuro}&1&\SI{45}{\%}&\SI{0}{\sieuro}\\
12 &\textbf{Ölfreie Vorpumpe IDP3} (G7078BA\#999)\newline Standardvorpumpe durch ölfreie Scrollpumpe IDP3 ersetzen: leiser, vibrationsarm, ölfrei, einfach zu warten, günstigere Betriebskosten.\newline Listenpreis: \SI{2277}{\sieuro}&1&\SI{99,9999}{\%}&\SI{0}{\sieuro}\\
\hline
\end{longtable}
\end{center}
\vspace{-2cm}
\begin{flushright}
\begin{tabular}{|rr|}
\hline
\textbf{Summe netto} & \SI{114824,05}{\sieuro}\\
\textbf{Versand und Bereitstellungskosten (3\%)} & \SI{2650}{\sieuro}\\
\textbf{Gesamtsumme netto} & \SI{117474,05}{\sieuro}\\
\textbf{Umsatzsteuer (19\%)} & \SI{22320,0695}{\sieuro}\\
\textbf{Gesamtsumme brutto} & \SI{139794,1195}{\sieuro}\\
\hline
\end{tabular}
\end{flushright}
Der Betrag versteht sich zzgl. der gesetzlichen Steuern.\\
Diese werden im Rechnungszeitraum auf der Rechnung gesondert ausgewiesen.\\
Zahlungsbedingungen: 30 Tage netto ab Rechnungsdatum.\\
Incoterm (2010) für Lieferungen innerhalb Deutschlands: DDP.
\begin{small}
\textbf{Gewährleistung:}\\
Die Gewährleistung für Zubehör und Ersatzteilprodukte und für Analytik-Hardwareprodukte beträgt 12 Monate.
\textbf{Hinweis:}\\
Für den Verkauf der in diesem Angebot aufgeführten Standard-Produkte und -Services gelten die aktuellen \emph{Agilent Geschäftsbedingungen} und alle sonstigen anwendbaren Zusatzbedingungen sowie zusätzliche Bedingungen, soweit darauf hier Bezug genommen wird. Soweit Produkte oder Services nach speziellen Kundenanforderungen hergestellt, konfiguriert oder angepasst werden, gelten für den Verkauf aller in diesem Angebot aufgeführten Produkte und Services die aktuellen \emph{Agilent Geschäftsbedingungen für kundenspezifische Produkte} und alle sonstigen anwendbaren Zusatzbedingungen sowie zusätzliche Bedingungen, soweit darauf hier Bezug genommen wird. Eine Kopie der maßgeblichen Bedingungen ist entweder beigefügt oder wurde Ihnen bereits zur Verfügung gestellt. Sollten Sie keine Kopie erhalten haben oder eine weitere Kopie benötigen, setzen Sie sich bitte mit uns in Verbindung. Soweit Sie mit Agilent eine gesonderte Vereinbarung getroffen haben, die den Verkauf der in diesem Angebot aufgeführten Produkte und Services umfasst, sind die Bestimmungen dieser Vereinbarung anwendbar. Abweichende oder ergänzende Vereinbarungen, insbesondere widersprechende Geschäftsbedingungen, sind nur gültig, wenn sie ausdrücklich schriftlich vereinbart worden sind. Die angegebenen Daten zur Verfügbarkeit von Produkten und Services sind vorläufig. Die tatsächlichen Lieferzeiten bzw. Lieferperioden werden Ihnen bei Auftragsbestätigung mitgeteilt. Waren, Technologien oder Software, die aus den Vereinigten Staaten von Amerika (\emph{USA}) oder anderen exportierenden Ländern ausgeführt werden, unterliegen den Ausfuhrbestimmungen der USA sowie anderer Rechtsordnungen. Bei Ausfuhr ist der Kunde dafür verantwortlich, dass die anwendbaren Ausfuhrbestimmungen eingehalten werden.
\end{small}
\begin{scriptsize}
Agilent Technologies Deutschland GmbH, Hewlett-Packard-Str. 8, D-76337 Waldbronn\\
Telefon +49 (0)7243-602-0\\
USt.-IdNr.: DE812729296, WEEE-Reg.-Nr. DE 86631749\\
Sitz der Gesellschaft: Waldbronn Amtsgericht Mannheim, HRB 723782\\
Geschäftsführer: Dr. Andreas Kistner (Vorsitzender der Geschäftsführung), Armin Jehle, Norbert Sabatzki, Dr. Knut Wintergerst\\
\href{www.agilent.com}{www.agilent.com}
\end{scriptsize}
\end{document}

@ -0,0 +1,13 @@
# Part Number Opt PL Description Qty Price EUR Breaks EUR Uplift % Total Discount % Net EUR Total EUR Sales Discount YA9% Contractual Discount Y99% Promotion Discount Y07% Demo Discount Y04% PH Code PH Description YMax
1 G4513A AZ 7693A automatischer Probengeber 1 9476 0 0 45 5211.8 5211.8 45 0 0 0 ISG100G141 Autosampler
2 G4514A AZ 7693A Probenteller, 150 Probenflaschen 2 11092 0 0 45 6100.6 12201.2 45 0 0 0 ISG100G141 Autosampler
3 G3540A AZ Agilent 8890 GC-System Kundenspezifisch 1 20258 0 0 45 11141.9 11141.9 45 0 0 0 ISG100G111 6890 GC system
4 G3540A 151 AZ Multimode-Einlass, LN2 oder Luftkuehlung 2 12221 0 0 45 6721.55 13443.1 45 0 0 0
5 G3540A 201 AZ MSD-Interface 1 2494 0 0 45 1371.7 1371.7 45 0 0 0
6 G3540A 211 AZ 8890 FID Zubeh. optimiert f. Kapillare 1 5124 0 0 45 2818.2 2818.2 45 0 0 0
7 G3540A 305 AZ Werksseitige Leitung f. Schnellinstall. 1 569 0 0 45 312.95 312.95 45 0 0 0
8 122-1334UI JW DB-624 UI 30m, 0.25mm, 1.40u 1 831 0 0 45 457.05 457.05 45 0 0 0 CSCG25C25V SpecApps Volatile
9 122-5532UI JW DB-5MS Ultra Inert 30m, 0,25mm, 0,25um 1 841 0 0 45 462.55 462.55 45 0 0 0 CSCG16C16B GC/MS UI 5-type
10 G7078BA BZ 5977B Inert Plus MSD Turbo EI/CI-Paket 1 122552 0 0 45 67403.6 67403.6 45 0 0 0 ISG310G310 GCMS SQ Bundle
11 G7078BA 245 BZ GC/MSD EI/CI fuer 8890 GC 1 0 0 0 45 0 0 45 0 0 0
12 G7078BA 999 BZ Oelfreie IDP3-Scrollp. ersetzen 1 2277 0 0 99.9999 0 0 99.9999 0 0 0 ISG310G310 GCMS SQ Bundle
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 G4513A AZ 7693A automatischer Probengeber 1 9476 0 0 45 5211.8 5211.8 45 0 0 0 ISG100G141 Autosampler
3 2 G4514A AZ 7693A Probenteller, 150 Probenflaschen 2 11092 0 0 45 6100.6 12201.2 45 0 0 0 ISG100G141 Autosampler
4 3 G3540A AZ Agilent 8890 GC-System Kundenspezifisch 1 20258 0 0 45 11141.9 11141.9 45 0 0 0 ISG100G111 6890 GC system
5 4 G3540A 151 AZ Multimode-Einlass, LN2 oder Luftkuehlung 2 12221 0 0 45 6721.55 13443.1 45 0 0 0
6 5 G3540A 201 AZ MSD-Interface 1 2494 0 0 45 1371.7 1371.7 45 0 0 0
7 6 G3540A 211 AZ 8890 FID Zubeh. optimiert f. Kapillare 1 5124 0 0 45 2818.2 2818.2 45 0 0 0
8 7 G3540A 305 AZ Werksseitige Leitung f. Schnellinstall. 1 569 0 0 45 312.95 312.95 45 0 0 0
9 8 122-1334UI JW DB-624 UI 30m, 0.25mm, 1.40u 1 831 0 0 45 457.05 457.05 45 0 0 0 CSCG25C25V SpecApps Volatile
10 9 122-5532UI JW DB-5MS Ultra Inert 30m, 0,25mm, 0,25um 1 841 0 0 45 462.55 462.55 45 0 0 0 CSCG16C16B GC/MS UI 5-type
11 10 G7078BA BZ 5977B Inert Plus MSD Turbo EI/CI-Paket 1 122552 0 0 45 67403.6 67403.6 45 0 0 0 ISG310G310 GCMS SQ Bundle
12 11 G7078BA 245 BZ GC/MSD EI/CI fuer 8890 GC 1 0 0 0 45 0 0 45 0 0 0
13 12 G7078BA 999 BZ Oelfreie IDP3-Scrollp. ersetzen 1 2277 0 0 99.9999 0 0 99.9999 0 0 0 ISG310G310 GCMS SQ Bundle