import EFCore elements from Gremlin

pull/1/head
Sascha 2022-11-17 10:03:37 +07:00
parent ee8aaf695a
commit e3a09c5235
57 changed files with 209930 additions and 60 deletions

@ -0,0 +1,19 @@
{
// Verwendet IntelliSense zum Ermitteln möglicher Attribute.
// Zeigen Sie auf vorhandene Attribute, um die zugehörigen Beschreibungen anzuzeigen.
// Weitere Informationen finden Sie unter https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/bin/Debug/dotnet-7.0/Gremlin_BlazorServer.dll",
"args": [],
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"stopAtEntry": false
},
]
}

@ -2,7 +2,7 @@
using System.Diagnostics;
using System.Windows;
namespace Gremlin
namespace Gremlin_BlazorServer
{
internal class ErrorHandler
{

@ -1,8 +1,8 @@
using Gremlin.GremlinData.EntityClasses;
using Gremlin.MVVM.ViewModels;
using Gremlin_BlazorServer.GremlinData.EntityClasses;
using Gremlin_BlazorServer.MVVM.ViewModels;
using System.Windows.Data;
namespace Gremlin.MVVM.Models
namespace Gremlin_BlazorServer.MVVM.Models
{
public class ContactModel
{

@ -1,11 +1,11 @@
using Caliburn.Micro;
using Gremlin.GremlinData.EntityClasses;
using Gremlin.GremlinUtilities;
using Gremlin_BlazorServer.GremlinData.EntityClasses;
using Gremlin_BlazorServer.GremlinUtilities;
using System;
using System.Diagnostics.Contracts;
using System.Windows.Data;
namespace Gremlin.MVVM.ViewModels
namespace Gremlin_BlazorServer.MVVM.ViewModels
{
public class ContactViewModel : PropertyChangedBase
{

@ -1,13 +0,0 @@
namespace Gremlin_BlazorServer.Data
{
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}
}

@ -1,20 +0,0 @@
namespace Gremlin_BlazorServer.Data
{
public class WeatherForecastService
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
public Task<WeatherForecast[]> GetForecastAsync(DateOnly startDate)
{
return Task.FromResult(Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
}).ToArray());
}
}
}

@ -0,0 +1,33 @@
using System;
using System.Diagnostics;
namespace Gremlin_BlazorServer
{
internal class ErrorHandler
{
public static void ShowErrorInMessageBox(Exception ex)
{
Debug.Log(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
public static void ShowErrorInMessageBox(Exception ex, string title)
{
Debug.Log(ex.Message, title, MessageBoxButton.OK, MessageBoxImage.Error);
}
public static void ShowErrorInDebug(Exception ex)
{
Debug.Log(ex.Message);
}
public static void ShowErrorMessage(string message)
{
Debug.Log(message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
public static void ShowInfoMessage(string message)
{
Debug.Log(message, "Info", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,61 @@
using System;
using System.Security;
namespace Gremlin_BlazorServer.GremlinData.DBClasses
{
internal class Encryption
{
private static readonly byte[] entropy = System.Text.Encoding.Unicode.GetBytes("My super power encryption made nearly by my own");
public static string EncryptString(SecureString input)
{
byte[] encryptedData = System.Security.Cryptography.ProtectedData.Protect(
System.Text.Encoding.Unicode.GetBytes(ToInsecureString(input)),
entropy,
System.Security.Cryptography.DataProtectionScope.CurrentUser);
return Convert.ToBase64String(encryptedData);
}
public static SecureString DecryptString(string encryptedData)
{
try
{
byte[] decryptedData = System.Security.Cryptography.ProtectedData.Unprotect(
Convert.FromBase64String(encryptedData),
entropy,
System.Security.Cryptography.DataProtectionScope.CurrentUser);
return ToSecureString(System.Text.Encoding.Unicode.GetString(decryptedData));
}
catch
{
return new SecureString();
}
}
public static SecureString ToSecureString(string input)
{
SecureString secure = new();
foreach (char c in input)
{
secure.AppendChar(c);
}
secure.MakeReadOnly();
return secure;
}
public static string ToInsecureString(SecureString input)
{
string returnValue = string.Empty;
IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(input);
try
{
returnValue = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr);
}
finally
{
System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);
}
return returnValue;
}
}
}

@ -0,0 +1,312 @@
using Gremlin_BlazorServer.GremlinData.EntityClasses;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Gremlin_BlazorServer.GremlinData.DBClasses
{
public class AccountConfiguration : IEntityTypeConfiguration<Account>
{
public void Configure(EntityTypeBuilder<Account> entity)
{
_ = entity.HasKey(e => e.AccountId);
_ = entity.HasMany(d => d.Contacts).WithOne(p => p.Account).IsRequired(true);
_ = entity.HasOne(d => d.AccountType).WithMany(p => p.Accounts).IsRequired(true).OnDelete(DeleteBehavior.Restrict);
_ = entity.HasOne(d => d.SubMarket).WithMany(p => p.Accounts).IsRequired(true).OnDelete(DeleteBehavior.Restrict);
_ = entity.HasAlternateKey(e => e.SAPAccountNumber); // =Unique
_ = entity.Property(e => e.AccountId).ValueGeneratedOnAdd();
_ = entity.Property(e => e.ParentAccountId);
_ = entity.Property(e => e.AccountName).IsRequired(true).HasMaxLength(250);
//.HasColumnType("VARCHAR(250)") ist überflüssig, da .HasMaxLength(250) VARCHAR(250) impliziert.
_ = entity.Property(e => e.Notes);
_ = entity.Property(e => e.Street).IsRequired(true).HasMaxLength(100);
_ = entity.Property(e => e.ZIP).IsRequired(true).HasColumnType("Char(5)");
_ = entity.Property(e => e.City).IsRequired(true).HasMaxLength(50);
_ = entity.Property(e => e.FloorOrBuilding).HasMaxLength(50);
_ = entity.Property(e => e.Longitude);
_ = entity.Property(e => e.Latitude);
_ = entity.Property(e => e.PhoneNumber).IsRequired(true).HasMaxLength(30);
_ = entity.Property(e => e.FaxNumber).HasMaxLength(30);
_ = entity.Property(e => e.Webpage).HasMaxLength(250);
_ = entity.Property(e => e.EMail).HasMaxLength(150);
_ = entity.Property(e => e.SAPAccountNumber).IsRequired(true);
_ = entity.Property(e => e.AccountCreatedInSAPOn).IsRequired(true);
_ = entity.Property(e => e.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataValidFrom).HasColumnType("DATETIME").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataValidUntil).HasColumnType("DATETIME").HasDefaultValueSql("'9999-12-31 23:59:59.000000'").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataVersionNumber).HasDefaultValue(1).IsRequired(true);
_ = entity.Property(e => e.DataVersionComment).HasDefaultValue("");
_ = entity.Property(e => e.DataStatus).IsRequired(true);
//.HasDefaultValue("Active") //Default-Wert wird nicht gesetzt?!? Bug in EF Core?
_ = entity.Property(e => e.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken(true);
//.IsRowVersion() impliziert .ValueGeneratedOnAddOrUpdate() und .IsConcurrencyToken(true)
_ = entity.Property(e => e.DataModificationByUser).HasColumnType("TINYTEXT").IsRequired(true).HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
}
}
public class ContactConfiguration : IEntityTypeConfiguration<Contact>
{
public void Configure(EntityTypeBuilder<Contact> entity)
{
_ = entity.HasKey(e => e.ContactId);
_ = entity.HasOne(p => p.Account).WithMany(d => d.Contacts).IsRequired(true);
//entity.HasAlternateKey(e => e.SAPContactNumber);
_ = entity.Property(e => e.ContactId);
_ = entity.Property(e => e.SAPContactNumber).IsRequired(true);
_ = entity.Property(e => e.AcademicTitle);
_ = entity.Property(e => e.FirstName);
_ = entity.Property(e => e.LastName).IsRequired(true);
_ = entity.Property(e => e.Gender);
//.IsRequired(true) darf nicht gesetzt werden, da sonst vom DB-Engine NULL nicht erlaubt wird (trotz Definition als Bool? im Code. MySQL kennt kein Bool, sondern wandelt das intern in Tinyint um).
_ = entity.Property(e => e.OptInStatus).HasDefaultValue(null);
_ = entity.Property(e => e.IsReference).HasDefaultValue(false);
_ = entity.Property(e => e.Notes);
_ = entity.Property(e => e.ValidatedContact).HasDefaultValue(false);
_ = entity.Property(e => e.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataValidFrom).HasColumnType("DATETIME").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataValidUntil).HasColumnType("DATETIME").HasDefaultValueSql("'9999-12-31 23:59:59.000000'").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataVersionNumber).HasDefaultValue(1).IsRequired(true);
_ = entity.Property(e => e.DataVersionComment).HasDefaultValue("");
_ = entity.Property(e => e.DataStatus).IsRequired(true);
//.HasDefaultValue("Active") //Default-Wert wird nicht gesetzt?!? Bug in EF Core?
_ = entity.Property(e => e.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken(true);
//.IsRowVersion() impliziert .ValueGeneratedOnAddOrUpdate() und .IsConcurrencyToken(true)
_ = entity.Property(e => e.DataModificationByUser).HasColumnType("TINYTEXT").IsRequired(true).HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
}
}
public class QuoteConfiguration : IEntityTypeConfiguration<Quote>
{
public void Configure(EntityTypeBuilder<Quote> entity)
{
_ = entity.HasKey(e => e.QuoteId);
_ = entity.HasMany(d => d.LineItems).WithOne(p => p.Quote).IsRequired(false).OnDelete(DeleteBehavior.Cascade);
_ = entity.Property(e => e.QuotationNumber).HasColumnType("VARCHAR(255)").IsRequired(true).ValueGeneratedOnAdd();
_ = entity.Property(e => e.QuotationDate).IsRequired(true).ValueGeneratedOnAdd();
_ = entity.Property(e => e.ValidUntil);
_ = entity.Property(e => e.ValidFor).IsRequired(true);
_ = entity.Ignore("SalesRep");
_ = entity.Property(e => e.TotalListprice);
_ = entity.Property(e => e.TotalDiscount);
_ = entity.Property(e => e.TotalNet);
_ = entity.Property(e => e.VAT);
_ = entity.Property(e => e.TotalGross);
_ = entity.Property(e => e.QuoteContains3PP).HasDefaultValue(false);
_ = entity.Property(e => e.QuoteContainsRB).HasDefaultValue(false);
_ = entity.Property(e => e.QuoteTemplate);
_ = entity.Property(e => e.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataValidFrom).HasColumnType("DATETIME").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataValidUntil).HasColumnType("DATETIME").HasDefaultValueSql("'9999-12-31 23:59:59.000000'").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataVersionNumber).HasDefaultValue(1).IsRequired(true);
_ = entity.Property(e => e.DataVersionComment).HasDefaultValue("");
_ = entity.Property(e => e.DataStatus).IsRequired(true);
//.HasDefaultValue("Active") //Default-Wert wird nicht gesetzt?!? Bug in EF Core?
_ = entity.Property(e => e.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken(true);
//.IsRowVersion() impliziert .ValueGeneratedOnAddOrUpdate() und .IsConcurrencyToken(true)
_ = entity.Property(e => e.DataModificationByUser).HasColumnType("TINYTEXT").IsRequired(true).HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
}
}
public class LineItemConfiguration : IEntityTypeConfiguration<LineItem>
{
public void Configure(EntityTypeBuilder<LineItem> entity)
{
_ = entity.HasKey(e => e.LineItemId);
_ = entity.HasOne(p => p.Quote).WithMany(d => d.LineItems).HasForeignKey(fk => fk.QuoteId).IsRequired(true).OnDelete(DeleteBehavior.Cascade);
_ = entity.Property(e => e.Position).IsRequired(true);
_ = entity.Property(e => e.Amount).IsRequired(true);
_ = entity.Property(e => e.ProductNumber).IsRequired(true);
_ = entity.Property(e => e.OptionNumber);
_ = entity.Property(e => e.SapShortDescription);
_ = entity.Property(e => e.SapLongDescription);
_ = entity.Property(e => e.ProductLine);
_ = entity.Property(e => e.TotalDiscount).IsRequired(true).HasDefaultValue(0);
_ = entity.Property(e => e.SalesDiscount).IsRequired(true).HasDefaultValue(0);
_ = entity.Property(e => e.PromotionalDiscount).IsRequired(true).HasDefaultValue(0);
_ = entity.Property(e => e.ContractualDiscount).IsRequired(true).HasDefaultValue(0);
_ = entity.Property(e => e.DemoDiscount).IsRequired(true).HasDefaultValue(0);
_ = entity.Property(e => e.ListPrice).IsRequired(true);
_ = entity.Property(e => e.ExtendedListPrice).IsRequired(true);
_ = entity.Property(e => e.NetPrice).IsRequired(true);
_ = entity.Property(e => e.Total).IsRequired(true);
_ = entity.Property(e => e.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataValidFrom).HasColumnType("DATETIME").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataValidUntil).HasColumnType("DATETIME").HasDefaultValueSql("'9999-12-31 23:59:59.000000'").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataVersionNumber).HasDefaultValue(1).IsRequired(true);
_ = entity.Property(e => e.DataVersionComment).HasDefaultValue("");
_ = entity.Property(e => e.DataStatus).IsRequired(true);
//.HasDefaultValue("Active") //Default-Wert wird nicht gesetzt?!? Bug in EF Core?
_ = entity.Property(e => e.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken(true);
//.IsRowVersion() impliziert .ValueGeneratedOnAddOrUpdate() und .IsConcurrencyToken(true)
_ = entity.Property(e => e.DataModificationByUser).HasColumnType("TINYTEXT").IsRequired(true).HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
}
}
public class ProductConfiguration : IEntityTypeConfiguration<Product>
{
public void Configure(EntityTypeBuilder<Product> entity)
{
_ = entity.HasKey(e => e.ProductId);
_ = entity.HasOne(d => d.CustomDescription).WithMany(p => p.Products).HasForeignKey("CustomDescriptionId").IsRequired(false).OnDelete(DeleteBehavior.SetNull); //.IsRequired() is just fyi, because it is overwritten by FK property nullability (nullable = optional relationship, non-nullable = required relationship)!
_ = entity.HasOne(p => p.ProductLine).WithMany(d => d.Products).HasForeignKey("ProductLineCode").IsRequired(true).OnDelete(DeleteBehavior.Restrict);
_ = entity.Property(e => e.CustomDescriptionId).IsRequired(false);
_ = entity.Property(e => e.ProductNumber).IsRequired(true);
_ = entity.Property(e => e.OptionNumber);
_ = entity.Property(e => e.SapShortDescription);
_ = entity.Property(e => e.SapLongDescription);
_ = entity.Property(e => e.Weight);
_ = entity.Property(e => e.ProductStatus);
_ = entity.Property(e => e.IntroductionDate);
_ = entity.Property(e => e.ListPrice).IsRequired(true);
_ = entity.Property(e => e.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataValidFrom).HasColumnType("DATETIME").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataValidUntil).HasColumnType("DATETIME").HasDefaultValueSql("'9999-12-31 23:59:59.000000'").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataVersionNumber).HasDefaultValue(1).IsRequired(true);
_ = entity.Property(e => e.DataVersionComment).HasDefaultValue("");
_ = entity.Property(e => e.DataStatus).IsRequired(true);
//.HasDefaultValue("Active") //Default-Wert wird nicht gesetzt?!? Bug in EF Core?
_ = entity.Property(e => e.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken(true);
//.IsRowVersion() impliziert .ValueGeneratedOnAddOrUpdate() und .IsConcurrencyToken(true)
_ = entity.Property(e => e.DataModificationByUser).HasColumnType("TINYTEXT").IsRequired(true).HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
}
}
public class CustomDescriptionConfiguration : IEntityTypeConfiguration<CustomDescription>
{
public void Configure(EntityTypeBuilder<CustomDescription> entity)
{
_ = entity.HasKey(e => e.CustomDescriptionId);
_ = entity.HasMany(p => p.Products).WithOne(d => d.CustomDescription).IsRequired(false);
_ = entity.HasOne(p => p.Supplier).WithMany(d => d.CustomDescriptions).IsRequired(true);
_ = entity.Property(e => e.ProductNumber).IsRequired(true);
_ = entity.Property(e => e.OptionNumber);
_ = entity.Property(e => e.Heading).IsRequired(true);
_ = entity.Property(e => e.DescriptionText);
_ = entity.Property(e => e.CoverletterText);
_ = entity.Property(e => e.Notes);
_ = entity.Property(e => e.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataValidFrom).HasColumnType("DATETIME").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataValidUntil).HasColumnType("DATETIME").HasDefaultValueSql("'9999-12-31 23:59:59.000000'").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataVersionNumber).HasDefaultValue(1).IsRequired(true);
_ = entity.Property(e => e.DataVersionComment).HasDefaultValue("");
_ = entity.Property(e => e.DataStatus).IsRequired(true);
//.HasDefaultValue("Active") //Default-Wert wird nicht gesetzt?!? Bug in EF Core?
_ = entity.Property(e => e.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken(true);
//.IsRowVersion() impliziert .ValueGeneratedOnAddOrUpdate() und .IsConcurrencyToken(true)
_ = entity.Property(e => e.DataModificationByUser).HasColumnType("TINYTEXT").IsRequired(true).HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
}
}
public class ProductLineConfiguration : IEntityTypeConfiguration<ProductLine>
{
public void Configure(EntityTypeBuilder<ProductLine> entity)
{
_ = entity.HasMany(p => p.Products).WithOne(d => d.ProductLine).IsRequired(true).OnDelete(DeleteBehavior.Restrict);
_ = entity.Property(e => e.ProductLineDescription).IsRequired(true);
_ = entity.Property(e => e.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataValidFrom).HasColumnType("DATETIME").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataValidUntil).HasColumnType("DATETIME").HasDefaultValueSql("'9999-12-31 23:59:59.000000'").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataVersionNumber).HasDefaultValue(1).IsRequired(true);
_ = entity.Property(e => e.DataVersionComment).HasDefaultValue("");
_ = entity.Property(e => e.DataStatus).IsRequired(true);
//.HasDefaultValue("Active") //Default-Wert wird nicht gesetzt?!? Bug in EF Core?
_ = entity.Property(e => e.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken(true);
//.IsRowVersion() impliziert .ValueGeneratedOnAddOrUpdate() und .IsConcurrencyToken(true)
_ = entity.Property(e => e.DataModificationByUser).HasColumnType("TINYTEXT").IsRequired(true).HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
}
}
public class AccountTypeConfiguration : IEntityTypeConfiguration<AccountType>
{
public void Configure(EntityTypeBuilder<AccountType> entity)
{
//entity.HasKey(e => e.AccountTypeCode);
//entity.HasMany(p => p.Accounts).WithOne(d => d.AccountType); //already defined in class Account
_ = entity.Property(e => e.AccountTypeCode).IsRequired(true).HasColumnType("Char(3)");
_ = entity.Property(e => e.AccountTypeDescription).HasColumnType("Varchar(1000)").IsRequired(true);
_ = entity.Property(e => e.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataValidFrom).HasColumnType("DATETIME").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataValidUntil).HasColumnType("DATETIME").HasDefaultValueSql("'9999-12-31 23:59:59.000000'").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataVersionNumber).HasDefaultValue(1).IsRequired(true);
_ = entity.Property(e => e.DataVersionComment).HasDefaultValue("");
_ = entity.Property(e => e.DataStatus).IsRequired(true);
//.HasDefaultValue("Active") //Default-Wert wird nicht gesetzt?!? Bug in EF Core?
_ = entity.Property(e => e.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken(true);
//.IsRowVersion() impliziert .ValueGeneratedOnAddOrUpdate() und .IsConcurrencyToken(true)
_ = entity.Property(e => e.DataModificationByUser).HasColumnType("TINYTEXT").IsRequired(true).HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
}
}
public class SubMarketConfiguration : IEntityTypeConfiguration<SubMarket>
{
public void Configure(EntityTypeBuilder<SubMarket> entity)
{
//entity.HasKey(e => e.SubMarketCode);
//entity.HasMany(p => p.Accounts).WithOne(d => d.SubMarket); //already defined in class Account
_ = entity.Property(e => e.SubMarketCode).HasColumnType("Char(3)");
_ = entity.Property(e => e.SubMarketDescription).HasColumnType("Varchar(1000)").IsRequired(true);
_ = entity.Property(e => e.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataValidFrom).HasColumnType("DATETIME").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataValidUntil).HasColumnType("DATETIME").HasDefaultValueSql("'9999-12-31 23:59:59.000000'").ValueGeneratedOnAdd();
_ = entity.Property(e => e.DataVersionNumber).HasDefaultValue(1).IsRequired(true);
_ = entity.Property(e => e.DataVersionComment).HasDefaultValue("");
_ = entity.Property(e => e.DataStatus).IsRequired(true);
//.HasDefaultValue("Active") //Default-Wert wird nicht gesetzt?!? Bug in EF Core?
_ = entity.Property(e => e.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken(true);
//.IsRowVersion() impliziert .ValueGeneratedOnAddOrUpdate() und .IsConcurrencyToken(true)
_ = entity.Property(e => e.DataModificationByUser).HasColumnType("TINYTEXT").IsRequired(true).HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
}
}
public class RegisteredUserConfiguration : IEntityTypeConfiguration<RegisteredUser>
{
public void Configure(EntityTypeBuilder<RegisteredUser> builder)
{
_ = builder.HasKey(e => e.RegisteredUserID);
_ = builder.HasMany(d => d.RUSettings).WithOne(p => p.RegisteredUser).IsRequired(true);
_ = builder.Property(e => e.UserName).IsRequired(true);
_ = builder.Property(e => e.PasswordHash).IsRequired(true);
_ = builder.Property(e => e.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = builder.Property(e => e.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken(true);
_ = builder.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> builder)
{
_ = builder.HasKey(e => e.RUSettingsID);
_ = builder.HasOne(d => d.RegisteredUser).WithMany(p => p.RUSettings).IsRequired(true);
_ = builder.Property(e => e.SettingKey).IsRequired(true);
_ = builder.Property(e => e.SettingValue).IsRequired(true);
_ = builder.Property(e => e.DataCreationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP").ValueGeneratedOnAdd();
_ = builder.Property(e => e.DataModificationDate).HasColumnType("TIMESTAMP").HasDefaultValueSql("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP").ValueGeneratedOnAddOrUpdate().IsConcurrencyToken(true);
_ = builder.Property(e => e.DataModificationByUser).HasColumnType("TINYTEXT").HasDefaultValueSql("ON INSERT CURRENT_USER() ON UPDATE CURRENT_USER()");
}
}
}

@ -0,0 +1,71 @@
using Gremlin_BlazorServer.GremlinData.EntityClasses;
using Microsoft.EntityFrameworkCore;
using System;
namespace Gremlin_BlazorServer.GremlinData.DBClasses
{
public class GremlinContext : DbContext
{
public DbSet<Contact> Contacts { get; set; }
public DbSet<Account> Accounts { get; set; }
public DbSet<Quote> Quotes { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<LineItem> LineItems { get; set; }
public DbSet<CustomDescription> CustomDescriptions { get; set; }
public DbSet<ProductLine> ProductLines { get; set; }
public DbSet<AccountType> AccountTypes { get; set; }
public DbSet<SubMarket> SubMarkets { get; set; }
public DbSet<RUSettings> RUSettings { get; set; }
public DbSet<RegisteredUser> RegisteredUser { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
string connectionString = $"server={Properties.Settings.Default.server};" +
$"port={Properties.Settings.Default.port};" +
$"database={Properties.Settings.Default.database};" +
$"user={Properties.Settings.Default.user};" +
$"password={Encryption.ToInsecureString(Encryption.DecryptString(Properties.Settings.Default.password))};" +
$"SslMode={Properties.Settings.Default.SslMode};" +
$"SslCa={Properties.Settings.Default.SslCA}";
try
{
_ = optionsBuilder
.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString))
//mySqlOptionsAction => mySqlOptionsAction.CharSetBehavior(Pomelo.EntityFrameworkCore.MySql.Infrastructure.CharSetBehavior.NeverAppend)).EnableDetailedErrors()
.EnableSensitiveDataLogging()
.EnableDetailedErrors();
}
catch (Exception ex)
{
ErrorHandler.ShowErrorInMessageBox(ex);
ChooseDB chooseDB = new();
_ = chooseDB.ShowDialog();
OnConfiguring(optionsBuilder);
throw;
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//wozu dient die folgende Zeile?
base.OnModelCreating(modelBuilder);
////alle Fluent-Konfigurationen aufrufen:
//TO BE TESTED!
_ = modelBuilder.ApplyConfigurationsFromAssembly(typeof(GremlinContext).Assembly);
////Fluent-Konfiguration einzeln für eine Entity aufrufen:
//new AccountConfiguration().Configure(modelBuilder.Entity<Account>());
//new ContactConfiguration().Configure(modelBuilder.Entity<Contact>());
//new QuoteConfiguration().Configure(modelBuilder.Entity<Quote>());
//new ProductConfiguration().Configure(modelBuilder.Entity<Product>());
//new LineItemConfiguration().Configure(modelBuilder.Entity<LineItem>());
//new CustomDescriptionConfiguration().Configure(modelBuilder.Entity<CustomDescription>());
//new ProductLineConfiguration().Configure(modelBuilder.Entity<ProductLine>());
//new AccountTypeConfiguration().Configure(modelBuilder.Entity<AccountType>());
//new SubMarketConfiguration().Configure(modelBuilder.Entity<SubMarket>());
}
}
}

@ -0,0 +1,13 @@
namespace Gremlin_BlazorServer.GremlinData.DBClasses
{
internal class GremlinTypeConverter
{
internal static object Convert(string stringToConvert)
{
//noch nicht implementiert.
//für vollkommen generischen Importer
//
return default;
}
}
}

@ -0,0 +1,65 @@
using Gremlin_BlazorServer.GremlinData.EntityClasses;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.CompilerServices;
using static Gremlin_BlazorServer.GremlinData.EntityClasses.Enums;
namespace Gremlin_BlazorServer.GremlinData.DBClasses
{
public static class MetaDataSetter
{
private static readonly DateTime FarInTheFuture = DateTime.Parse("2050-12-31t00:00:00.000000z", CultureInfo.CurrentCulture);
public static IMetadata ForImport(
IMetadata entity,
string datamodifiedby = "",
string dataversioncomment = "",
[CallerMemberName] string callername = "")
{
_ = SetMetaData(entity, datamodifiedby, dataversioncomment, callername);
return entity;
}
public static List<IMetadata> ForImport(
List<IMetadata> entities,
string datamodifiedby = "",
string dataversioncomment = "",
[CallerMemberName] string callername = "")
{
//check if entities implements IMetaData:
//Ist das überhaupt nötig?
if ((entities is IMetadata) == false)
{
//no action / return list unchanged
return entities;
}
//set metadata
foreach (IMetadata entity in entities)
{
_ = SetMetaData(entity, datamodifiedby, dataversioncomment, callername);
}
return entities;
}
private static IMetadata SetMetaData(
IMetadata entity,
string datamodifiedby = "",
string dataversioncomment = "",
[CallerMemberName] string callername = "")
{
entity.DataCreationDate = DateTime.Now;
entity.DataModificationDate = DateTime.Now;
entity.DataModificationByUser = datamodifiedby == "" ? callername : datamodifiedby;
entity.DataStatus = Status.Active.ToString();
entity.DataValidFrom = DateTime.Now;
entity.DataValidUntil = FarInTheFuture;
entity.DataVersionNumber++;
entity.DataVersionComment = dataversioncomment;
return entity;
}
}
}

@ -0,0 +1,26 @@
using Gremlin_BlazorServer.GremlinData.EntityClasses;
using System.Collections.Generic;
using System.Text;
namespace Gremlin_BlazorServer.GremlinData.DBClasses
{
public class ProductEqualityComparer : IEqualityComparer<Product>
{
public bool Equals(Product product1, Product product2)
{
return !((product1 != null || product2 != null)
&& !(product1 != null && product2 != null
&& product1.ProductNumber == product2.ProductNumber
&& product1.OptionNumber == product2.OptionNumber
&& product1.BreakRangeFrom == product2.BreakRangeFrom
&& product1.BreakRangeTo == product2.BreakRangeTo));
}
public int GetHashCode(Product product)
{
StringBuilder sb = new();
_ = sb.Append(product.ProductNumber).Append(product.OptionNumber).Append(product.BreakRangeFrom).Append(product.BreakRangeTo);
return sb.ToString().GetHashCode();
}
}
}

@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
namespace Gremlin_BlazorServer.GremlinData.EntityClasses
{
public class Account : IMetadata
//: IEquatable<Account>
{
//primary key:
public uint AccountId { get; set; }
//foreign keys:
public IList<Contact> Contacts { get; set; }
public uint? ParentAccountId { get; set; }
public AccountType AccountType { get; set; }
public SubMarket SubMarket { get; set; }
public IList<CustomDescription> CustomDescriptions { get; set; }
//class properties:
public string AccountName { get; set; }
public string Notes { get; set; }
public string Street { get; set; }
public uint ZIP { get; set; }
public string City { get; set; }
public string FloorOrBuilding { get; set; }
public float Longitude { get; set; }
public float Latitude { get; set; }
public string PhoneNumber { get; set; }
public string FaxNumber { get; set; }
public string Webpage { get; set; }
public string EMail { get; set; }
//Agilent-specific Properties:
public uint SAPAccountNumber { get; set; }
public DateTime AccountCreatedInSAPOn { get; set; }
//metadata:
public DateTime DataCreationDate { get; set; }
public DateTime DataModificationDate { get; set; }
public DateTime DataValidFrom { get; set; }
public DateTime DataValidUntil { get; set; }
public string DataModificationByUser { get; set; }
public uint DataVersionNumber { get; set; }
public string DataVersionComment { get; set; }
public string DataStatus { get; set; }
//IBase
//tbd
public Account()
{
}
//public bool Equals(Account other)
//{
// if (other == null) return false;
// if (this == null) return false;
// if (this.SAPAccountNumber == other.SAPAccountNumber) return true;
// else return false;
//}
//public static bool operator ==(Account account1, Account account2)
//{
// if (account1.SAPAccountNumber == 0) return false;
// if (account2.SAPAccountNumber == 0) return false;
// if (account1.SAPAccountNumber == account2.SAPAccountNumber) return true;
// else return false;
//}
//public static bool operator !=(Account account1, Account account2)
//{
// if (account1.SAPAccountNumber == 0) return false;
// if (account2.SAPAccountNumber == 0) return false;
// if (account1.SAPAccountNumber == account2.SAPAccountNumber) return false;
// else return true;
//}
//public override bool Equals(object obj)
//{
// if (obj == null) return false;
// Account accountObj = obj as Account;
// if (accountObj == null) return false;
// else return base.Equals(obj);
//}
//public override int GetHashCode()
/////<summary>
/////Returns the (unique) SAP Account ID.
/////</summary>
//{
// return Convert.ToInt32(this.SAPAccountNumber);
//}
public List<Account> AddIfUniqueTo(List<Account> accounts)
{
if (accounts.Count > 0 && SAPAccountNumber == accounts[accounts.Count - 1].SAPAccountNumber)
{
return accounts;
}
foreach (Account account in accounts)
{
if (SAPAccountNumber == account.SAPAccountNumber)
{
return accounts;
}
}
accounts.Add(this);
return accounts;
}
}
}

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Gremlin_BlazorServer.GremlinData.EntityClasses
{
public class AccountType : IMetadata
{
//primary key:
//public uint AccountTypeId { get; set; }
[Key] //Fluent API .HasKey funktioniert nicht
public string AccountTypeCode { get; set; }
//navigation properties:
public IList<Account> Accounts { get; set; }
//class properties:
public string AccountTypeDescription { get; set; }
//metadata:
public DateTime DataCreationDate { get; set; }
public DateTime DataModificationDate { get; set; }
public DateTime DataValidFrom { get; set; }
public DateTime DataValidUntil { get; set; }
public string DataModificationByUser { get; set; }
public uint DataVersionNumber { get; set; }
public string DataVersionComment { get; set; }
public string DataStatus { get; set; }
}
}

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
namespace Gremlin_BlazorServer.GremlinData.EntityClasses
{
public class Contact : IMetadata
{
//primary key:
public uint ContactId { get; set; }
//foreign keys:
public uint AccountId { get; set; }
//navigation properties:
public Account Account { get; set; }
public IList<Quote> Quotes { get; set; }
//class properties:
public string AcademicTitle { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public byte Gender { get; set; }
public bool? OptInStatus { get; set; }
public string Department { get; set; }
public string Function { get; set; }
public string Room { get; set; }
public bool? IsReference { get; set; }
public string Notes { get; set; }
public string PhoneNumber { get; set; }
public string MobileNumber { get; set; }
public string EMail { get; set; }
public string PreferredContactMethod { get; set; }
public bool NoPhoneCalls { get; set; }
public bool EmailBounced { get; set; }
public bool NoHardcopyMailing { get; set; }
public bool ValidatedContact { get; set; }
//Agilent-specific Properties:
public int SAPContactNumber { get; set; }
public DateTime SAPContactCreationDate { get; set; }
public DateTime SAPContactModifiedDate { get; set; }
public string SAPJobFunction { get; set; }
public string SAPProductInterest { get; set; }
public string SAPApplicationInterest { get; set; }
public string SAPJobLevel { get; set; }
public string SAPCompetitiveIBase { get; set; }
//metadata:
public DateTime DataCreationDate { get; set; }
public DateTime DataModificationDate { get; set; }
public DateTime DataValidFrom { get; set; }
public DateTime DataValidUntil { get; set; }
public string DataModificationByUser { get; set; }
public uint DataVersionNumber { get; set; }
public string DataVersionComment { get; set; }
public string DataStatus { get; set; }
public Contact()
{
}
}
}

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
namespace Gremlin_BlazorServer.GremlinData.EntityClasses
{
public class CustomDescription : IMetadata
{
//primary key:
public uint CustomDescriptionId { get; set; }
//foreign keys:
//public uint ProductId { get; set; }
public uint AccountId { get; set; }
//navigation properties:
public IList<Product> Products { get; set; }
public Account Supplier { get; set; }
//class properties:
public string ProductNumber { get; set; }
public string OptionNumber { get; set; }
public string Heading { get; set; }
public string DescriptionText { get; set; }
public string CoverletterText { get; set; }
public string Notes { get; set; } //Hinweise, Tipps, Caveats, etc. für Konfiguration, Verwendung, Best Practice usw.
//Agilent-Specific properties:
//NONE
//metadata:
public DateTime DataCreationDate { get; set; }
public DateTime DataModificationDate { get; set; }
public DateTime DataValidFrom { get; set; }
public DateTime DataValidUntil { get; set; }
public string DataModificationByUser { get; set; }
public uint DataVersionNumber { get; set; }
public string DataVersionComment { get; set; }
public string DataStatus { get; set; }
//Constructors
public CustomDescription()
{
}
}
}

@ -0,0 +1,41 @@
namespace Gremlin_BlazorServer.GremlinData.EntityClasses
{
public class Enums
{
public enum Status : byte
{
Deleted = 0,
Archived = 1,
Obsolete = 2,
DescriptionUpdated = 3,
StatusUpdated = 4,
Active = 11,
New = 12, //implies also 'Active'
PriceUpdated = 13, //implies also 'Active'
}
public enum SupportStatus : byte
{
OutOfSupport = 0,
BestEffort = 1,
Supported = 2,
}
public enum OptInStatus : byte
{
OptOut = 0,
NotKnown = 1,
OptIn = 2,
}
public enum Gender : byte
{
Unknown = 0,
Male = 1,
Female = 2,
divers = 3,
}
}
}

@ -0,0 +1,16 @@
using System;
namespace Gremlin_BlazorServer.GremlinData.EntityClasses
{
public interface IMetadata
{
DateTime DataCreationDate { get; set; }
string DataModificationByUser { get; set; }
DateTime DataModificationDate { get; set; }
string DataStatus { get; set; }
DateTime DataValidFrom { get; set; }
DateTime DataValidUntil { get; set; }
string DataVersionComment { get; set; }
uint DataVersionNumber { get; set; }
}
}

@ -0,0 +1,44 @@
using System;
namespace Gremlin_BlazorServer.GremlinData.EntityClasses
{
public class LineItem : IMetadata
{
//primary key:
public uint LineItemId { get; set; }
//foreign keys:
public uint QuoteId { get; set; }
//navigation properties:
public Quote Quote { get; set; }
//class properties:
public ushort Position { get; set; }
public ushort Amount { get; set; }
public string ProductNumber { get; set; }
public string OptionNumber { get; set; }
public string SapShortDescription { get; set; }
public string SapLongDescription { get; set; }
public string ProductLine { get; set; }
public decimal TotalDiscount { get; set; }
public decimal SalesDiscount { get; set; }
public decimal PromotionalDiscount { get; set; }
public decimal ContractualDiscount { get; set; }
public decimal DemoDiscount { get; set; }
public decimal ListPrice { get; set; }
public decimal ExtendedListPrice { get; set; }
public decimal NetPrice { get; set; }
public decimal Total { get; set; }
//metadata:
public DateTime DataCreationDate { get; set; }
public string DataModificationByUser { get; set; }
public DateTime DataModificationDate { get; set; }
public string DataStatus { get; set; }
public DateTime DataValidFrom { get; set; }
public DateTime DataValidUntil { get; set; }
public string DataVersionComment { get; set; }
public uint DataVersionNumber { get; set; }
}
}

@ -0,0 +1,49 @@
using System;
namespace Gremlin_BlazorServer.GremlinData.EntityClasses
{
public class Product : IMetadata
{
//primary key:
public uint ProductId { get; set; }
//navigation properties:
public CustomDescription CustomDescription { get; set; }
public ProductLine ProductLine { get; set; }
//foreign keys
public uint? CustomDescriptionId { get; set; }
public string ProductLineCode { get; set; }
//Agilent-specific properties:
public string ProductNumber { get; set; }
public string OptionNumber { get; set; }
public string SapShortDescription { get; set; }
public string SapLongDescription { get; set; }
public float Weight { get; set; }
public string ProductStatus { get; set; }
public DateTime IntroductionDate { get; set; }
public decimal ListPrice { get; set; }
public bool HasBreakPrices { get; set; }
public int BreakRangeFrom { get; set; }
public int BreakRangeTo { get; set; }
//metadata:
public DateTime DataCreationDate { get; set; }
public DateTime DataModificationDate { get; set; }
public DateTime DataValidFrom { get; set; }
public DateTime DataValidUntil { get; set; }
public string DataModificationByUser { get; set; }
public uint DataVersionNumber { get; set; }
public string DataVersionComment { get; set; }
public string DataStatus { get; set; }
//Constructors
public Product()
{
}
}
}

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Gremlin_BlazorServer.GremlinData.EntityClasses
{
public class ProductLine : IMetadata
{
//primary key:
//public uint ProductLineId { get; set; }
[Key]
public string ProductLineCode { get; set; }
//navigation properties:
public List<Product> Products { get; set; }
//class properties:
public string ProductLineDescription { get; set; }
//metadata:
public DateTime DataCreationDate { get; set; }
public DateTime DataModificationDate { get; set; }
public DateTime DataValidFrom { get; set; }
public DateTime DataValidUntil { get; set; }
public string DataModificationByUser { get; set; }
public uint DataVersionNumber { get; set; }
public string DataVersionComment { get; set; }
public string DataStatus { get; set; }
}
}

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
namespace Gremlin_BlazorServer.GremlinData.EntityClasses
{
public class Quote : IMetadata
{
//primary key:
public uint QuoteId { get; set; }
//foreign keys:
public uint? ContactId { get; set; }
//navigation properties:
public Contact Recipient { get; set; }
public IList<LineItem> LineItems { get; set; }
//class properties:
public Contact SalesRep { get; set; }
public string QuotationNumber { get; set; }
public DateTime QuotationDate { get; set; }
public DateTime ValidUntil { get; set; }
public byte ValidFor { get; set; }
public decimal TotalListprice { get; set; }
public decimal TotalDiscount { get; set; }
public decimal TotalNet { get; set; }
public float VAT { get; set; }
public decimal TotalGross { get; set; }
public bool QuoteContains3PP { get; set; }
public bool QuoteContainsRB { get; set; }
public string QuoteTemplate { get; set; }
//metadata:
public DateTime DataCreationDate { get; set; }
public string DataModificationByUser { get; set; }
public DateTime DataModificationDate { get; set; }
public string DataStatus { get; set; }
public DateTime DataValidFrom { get; set; }
public DateTime DataValidUntil { get; set; }
public string DataVersionComment { get; set; }
public uint DataVersionNumber { get; set; }
internal Quote()
{
}
}
}

@ -0,0 +1,61 @@
using System;
namespace Gremlin_BlazorServer.GremlinData.EntityClasses
{
public class RUSettings : IDisposable
{
private bool disposedValue;
//primary key
public uint RUSettingsID { get; set; }
//forgein key
public uint RegisteredUserID { get; set; }
//navigation properties
public RegisteredUser RegisteredUser { get; set; }
//class properties
public string SettingKey { get; set; }
public string SettingValue { get; set; }
//metadata (subset of IMetadata)
public DateTime DataCreationDate { get; set; }
public DateTime DataModificationDate { get; set; }
public string DataModificationByUser { get; set; }
//Constructur
public RUSettings()
{
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: Verwalteten Zustand (verwaltete Objekte) bereinigen
}
// TODO: Nicht verwaltete Ressourcen (nicht verwaltete Objekte) freigeben und Finalizer überschreiben
// TODO: Große Felder auf NULL setzen
disposedValue = true;
}
}
// // TODO: Finalizer nur überschreiben, wenn "Dispose(bool disposing)" Code für die Freigabe nicht verwalteter Ressourcen enthält
// ~RUSettings()
// {
// // Ändern Sie diesen Code nicht. Fügen Sie Bereinigungscode in der Methode "Dispose(bool disposing)" ein.
// Dispose(disposing: false);
// }
public void Dispose()
{
// Ändern Sie diesen Code nicht. Fügen Sie Bereinigungscode in der Methode "Dispose(bool disposing)" ein.
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
namespace Gremlin_BlazorServer.GremlinData.EntityClasses
{
public class RegisteredUser
{
//primary key
public uint RegisteredUserID { get; set; }
//navigation properties
public IList<RUSettings> RUSettings { get; set; }
//class properties
public string UserName { get; set; }
public string PasswordHash { get; set; }
//metadata (subset of IMetadata)
public DateTime DataCreationDate { get; set; }
public DateTime DataModificationDate { get; set; }
public string DataModificationByUser { get; set; }
//Constructur
public RegisteredUser()
{
}
}
}

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Gremlin_BlazorServer.GremlinData.EntityClasses
{
public class SubMarket : IMetadata
{
//primary key:
//public uint SubMarketId { get; set; }
[Key]
public string SubMarketCode { get; set; }
//navigation properties:
public IList<Account> Accounts { get; set; }
//class properties:
public string SubMarketDescription { get; set; }
//metadata
public DateTime DataCreationDate { get; set; }
public DateTime DataModificationDate { get; set; }
public DateTime DataValidFrom { get; set; }
public DateTime DataValidUntil { get; set; }
public string DataModificationByUser { get; set; }
public uint DataVersionNumber { get; set; }
public string DataVersionComment { get; set; }
public string DataStatus { get; set; }
}
}

@ -0,0 +1,18 @@
AccountType|AccountTypeDescription
FPC|Commercial
FPR|Contract Manufacturing CRM & Contract Research CRO
FPT|Contract Testing
FPV|Instrument IDR Distributor
FPN|Instrument National Distributor
FPP|Foreign Trade Org
FPG|Genomics/CSD Distributor
FPX|Regulated Distributor
FPS|Transactional Reseller
FPA|Value Added Reseller
FPO|OEM
FPW|Occasional resellers
NPU|University
NPR|Research Institute
NPG|Government
NPH|Hospital
SUP|Supplier

@ -0,0 +1,10 @@
AccountName|Street|ZIP|City|SAPAccountNumber|AccountEMail|PhoneNumber|AccountTypeCode|SubMarketCode|FaxNumber
Agilent Technologies|Hewlett-Packard-Str. 8|76337|Waldbronn|00000001|CustomerCare_Germany@agilent.com|+49 800 6031000|SUP|VEN|
Bios Analytical Ltd.|7 South Fens Enterprise Park//Fenton Way//PE16 6WA Chatteris//Cambridgeshire//United Kingdom|0|Chatteris, UNITED KINGDOM|00000002|contact@bios-analytical.com|+44 1354 693311|SUP|VAR|
Huber Kältemaschinenbau AG|Werner-von-Siemens-Straße 1|77656|Offenburg|00000003|sales@huber-online.com|0781 96030|SUP|SUP|
Van der Heijden Labortechnik GmbH|Tramsmeiers Berg 2|32694|Dörentrup|00000004|info@vdh-online.com|05265 945520|SUP|SUP|
OLE DICH Instrumentmakers ApS|18, Taarnfalkevej|2650|Hvidovre, DENMARK|00000005||+45 36784185|SUP|SUP|
S-prep GmbH|Im Amann 7|88662|Überlingen|00000006|info@s-prep.com|07551 932696|SUP|SUP|07551-932699
Hellma GmbH & Co. KG|Klosterrunsstraße 5|79379|Müllheim|00000007|info.de@hellma.com|07631 1820|SUP|SUP|
Glasside Technologies|Albany House, 82 Avenue Road//PE19 1LH St Neots, Cambridgeshire//United Kingdom|0|St Neots, Cambridgesgire, UNITED KINGDOM|00000008||-/-|SUP|SUP|
PIKE Technologies Inc.|6125 Cottonwood Drive//Madison, WI 53719//USA|53719|Madison (WI), USA|00000009|info@piketech.com|+1 608 274 2721|SUP|SUP|+1 608 274 0103

File diff suppressed because it is too large Load Diff

@ -0,0 +1,48 @@
ProductLineAbbreviation|ProductLineDescription
XF|Cell Analysis
LM|Lab Management
XA|Flow Cell
RB|Remarketed Instruments
GE| Genomics
9Z|Drugs of Abuse
9P|Sample Prep/Resins
9M|Research Products
9K|Dissolution & Other
9H|Vacuum Products
9F|AA/OES
9E|Drugs of Abuse
9C|Micro GC
ZZ|Common PL & Default
ZF|Expedite Freight
V1|Automation
MB|Particle Analysis
MA|Molecular Spectroscopy
LI|Software and Informatics
JW|GC Columns
CA|Mid Range GC
BZ|GC-MS
BC|LC Columns
AZ|Gas Phase Analysis
AJ|ICPMS
AB|Bio-consumables
AA|Instrument Supplies
8P|Analytical Parts Sup
89|LC-MS
74|Support Services
6P|Software and Professinal Services
6G|Other Local Products
58|Competitive Supplies
29|LC
AM|Amplicon Sequencing
RP|Reagent Partnership
CD|Companion Diagnostic
PT|Pathology
XB|Biotek
RM|Raman Spectroscopy
GS|Genomics Systems
AT|Parallel CE Instrument
SR|Bio Reagents
FS|Flexible Spending
BD|Nucleic Acid
UF|Microfluidics
3P|3rd Party Product

@ -0,0 +1,16 @@
SubMarketCode|SubMarketDescription
CCH|Chemical & Energy
CEN|Environmental
CFD|Food
CFR|Forensics
CMS|Material Science
COT|CA Other
LPH|Pharmaceutical
LBT|BioPharma
LGN|Generics
LRS|LS Research
DCT|Clinical Testing
LOT|LS Other
VEN|Analytical Instrument Vendor
VAR|VAR-Partner
SUP|Supplier

File diff suppressed because it is too large Load Diff

@ -0,0 +1,15 @@
# Part Number Opt PL Description Qty Price EUR Breaks EUR Uplift % Total Discount % Net EUR Total EUR Sales Discount YA9% Contractual Discount Y99% Promotion Discount Y07% Demo Discount Y04% PH Code PH Description YMax
1 G3540A AZ Agilent 8890 GC-System Kundenspezifisch 1 17070 0 0 52.52 8104.84 8104.84 32.52 20 0 0 ISG100G111 6890 GC system
2 G3540A 112 AZ 8890 100 psi Split/Splitless-Einlasszub. 1 4334 0 0 52.52 2057.78 2057.78 32.52 20 0 0
3 G3540A 204 AZ Midpoint-Backflush fuer GC/MS 1 2517 0 0 52.52 1195.07 1195.07 32.52 20 0 0
4 G3540A 310 AZ PSD-Modul f. CFT Pneum. Umschaltung 1 2881 0 0 52.52 1367.9 1367.9 32.52 20 0 0
5 G3540A 306 AZ Baugruppe Abluftblende 1 169 0 0 52.52 80.24 80.24 32.52 20 0 0
6 G4567A AZ 7650 Automatischer Fluessigprobengeber 1 14285 0 0 52.52 6782.52 6782.52 32.52 20 0 0 ISG100G140 Autosampler
7 5188-5246 58 Spritze, 1,0 uL, 23G, 42mm, Konusspitze 1 169 0 0 52.52 80.24 80.24 32.52 20 0 0 CSSP00SP10 Autosampler Syringes&Parts
8 G7077BA BZ 5977B Inert Plus MSD Turbo EI-Paket 1 83033 0 0 52.52 39424.07 39424.07 32.52 20 0 0 ISG310G310 GCMS SQ Bundle
9 G7077BA 245 BZ GC/MSD InertPlus EI fuer 8890 GC 1 0 0 0 52.52 0 0 32.52 20 0 0
10 G7077BA 325 BZ GCMSD Akad.-Option 1 -2283 0 0 52.52 -1083.97 -1083.97 32.52 20 0 0 ISG310G310 GCMS SQ Bundle
11 G7077BA 230 BZ ChemStation DA m. MassH-Einw. hinzufueg. 1 0 0 0 52.52 0 0 32.52 20 0 0
12 G7077BA 790 BZ Ohne Monitor 1 -171 0 0 52.52 -81.19 -81.19 32.52 20 0 0 ISG310G310 GCMS SQ Bundle
13 G1033C BZ Paketangebot: NIST MS-Spektrenbibliothek 1 6449 0 0 52.52 3061.99 3061.99 32.52 20 0 0 ISG400G440 MSD Libraries
14 H2620A - 0 956 0 0 20 764.8 0 20 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 G3540A AZ Agilent 8890 GC-System Kundenspezifisch 1 17070 0 0 52.52 8104.84 8104.84 32.52 20 0 0 ISG100G111 6890 GC system
3 2 G3540A 112 AZ 8890 100 psi Split/Splitless-Einlasszub. 1 4334 0 0 52.52 2057.78 2057.78 32.52 20 0 0
4 3 G3540A 204 AZ Midpoint-Backflush fuer GC/MS 1 2517 0 0 52.52 1195.07 1195.07 32.52 20 0 0
5 4 G3540A 310 AZ PSD-Modul f. CFT Pneum. Umschaltung 1 2881 0 0 52.52 1367.9 1367.9 32.52 20 0 0
6 5 G3540A 306 AZ Baugruppe Abluftblende 1 169 0 0 52.52 80.24 80.24 32.52 20 0 0
7 6 G4567A AZ 7650 Automatischer Fluessigprobengeber 1 14285 0 0 52.52 6782.52 6782.52 32.52 20 0 0 ISG100G140 Autosampler
8 7 5188-5246 58 Spritze, 1,0 uL, 23G, 42mm, Konusspitze 1 169 0 0 52.52 80.24 80.24 32.52 20 0 0 CSSP00SP10 Autosampler Syringes&Parts
9 8 G7077BA BZ 5977B Inert Plus MSD Turbo EI-Paket 1 83033 0 0 52.52 39424.07 39424.07 32.52 20 0 0 ISG310G310 GCMS SQ Bundle
10 9 G7077BA 245 BZ GC/MSD InertPlus EI fuer 8890 GC 1 0 0 0 52.52 0 0 32.52 20 0 0
11 10 G7077BA 325 BZ GCMSD Akad.-Option 1 -2283 0 0 52.52 -1083.97 -1083.97 32.52 20 0 0 ISG310G310 GCMS SQ Bundle
12 11 G7077BA 230 BZ ChemStation DA m. MassH-Einw. hinzufueg. 1 0 0 0 52.52 0 0 32.52 20 0 0
13 12 G7077BA 790 BZ Ohne Monitor 1 -171 0 0 52.52 -81.19 -81.19 32.52 20 0 0 ISG310G310 GCMS SQ Bundle
14 13 G1033C BZ Paketangebot: NIST MS-Spektrenbibliothek 1 6449 0 0 52.52 3061.99 3061.99 32.52 20 0 0 ISG400G440 MSD Libraries
15 14 H2620A - 0 956 0 0 20 764.8 0 20 0 0 0

@ -0,0 +1,102 @@
using Gremlin_BlazorServer.ViewModels;
using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
//using Outlook = Microsoft.Office.Interop.Outlook;
namespace Gremlin_BlazorServer.GremlinUtilities
{
internal static class FileIO
{
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));
using (Stream stream = assembly.GetManifestResourceStream(resourcePath))
using (StreamReader reader = new(stream))
{
return reader.ReadToEnd();
}
}
private static readonly Encoding defaultEncodingIfNoBom = Encoding.UTF8;
// public static string GetFilepathFromUser(string filter = "Delimited Data File|*.csv; *.txt; *.tsv")
// {
// string _filepath = "";
// OpenFileDialog dlg = new()
// {
// Multiselect = false,
// Filter = filter
// };
// if (dlg.ShowDialog() == true)
// {
// //Auswahl dlg.filenames an passende Objekte übergeben
// _filepath = dlg.FileName;
// }
// return _filepath;
// }
internal static void OpenFile(string path, string file, string type)
{
try
{
_ = Process.Start(path == "" ? $"{file}.{type}" : $"{path}\\{file}.{type}");
}
catch (Exception ex)
{
ErrorHandler.ShowErrorInMessageBox(ex);
}
}
public static Encoding GetEncoding(string fileName)
{
Stream fileStream = File.OpenRead(fileName);
using (StreamReader reader = new(fileStream, defaultEncodingIfNoBom, true))
{
_ = reader.Peek();
Encoding encoding = reader.CurrentEncoding;
return encoding;
}
}
// public static void WriteClipboardToTSV(string clipboard, QuoteViewModel quoteVM)
// {
// string datei = quoteVM.QuotePath + quoteVM.QuoteNumber + ".tsv";
// using StreamWriter writer = new(datei, false, Encoding.UTF8);
// {
// writer.WriteLine(clipboard);
// }
// }
//public static void SendQuoteViaMail(QuoteVM quoteVM)
//{
// Outlook.Application application = new();
// Outlook.MailItem mail = application.CreateItem(Outlook.OlItemType.olMailItem) as Outlook.MailItem;
// mail.Subject = quoteVM.QuoteNumber;
// Outlook.AddressEntry currentUser = application.Session.CurrentUser.AddressEntry;
// if (currentUser.Type == "EX")
// {
// Outlook.ExchangeUser manager = currentUser.GetExchangeUser().GetExchangeUserManager();
// // Add recipient using display name, alias, or smtp address
// mail.Recipients.Add(manager.PrimarySmtpAddress);
// mail.Recipients.ResolveAll();
// mail.Attachments.Add($"{quoteVM.QuoteNumber}.pdf", Outlook.OlAttachmentType.olByValue, Type.Missing, Type.Missing);
// mail.Send();
// }
//}
}
}

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Gremlin_BlazorServer.GremlinUtilities.GUClasses
{
internal class DataIdType
{
private readonly List<string> _matchedQualifiers;
private readonly int _numberOfQualifiers;
public string DataType { get; }
public List<string> Qualifiers { get; }
public int Score { get; private set; } = 0;
public bool AllQualifierMatched { get; private set; } = false;
public DataIdType(string DataType, IEnumerable<string> Qualifiers)
{
this.DataType = DataType;
this.Qualifiers = Qualifiers.ToList();
_numberOfQualifiers = this.Qualifiers.Count;
_matchedQualifiers = new();
}
public void AddFoundQualfier(string QualifierFound)
{
_matchedQualifiers.Add(QualifierFound);
Score++;
AllQualifierMatched = _matchedQualifiers.Count == _numberOfQualifiers;
}
public bool CheckForQualifier(string qualifier)
{
return Qualifiers.Contains(qualifier);
}
public void IncreaseScore(int value = 1)
{
Score += value;
}
public void ResetScore()
{
Score = 0;
}
public override bool Equals(object obj)
{
return obj is DataIdType type
&& DataType == type.DataType;
}
public override int GetHashCode()
{
return HashCode.Combine(DataType);
}
}
}

@ -0,0 +1,175 @@
using MoreLinq;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Gremlin_BlazorServer.GremlinUtilities.GUClasses
{
internal class DataIdentificator
{
//private readonly string _source; //Qualifier-Liste
private readonly Dictionary<string, int> _mappingTable; //Mapping Spaltenzahl <-> Property/(übersetzte) Spaltenüberschrift
public List<DataIdType> DataTypes { get; set; }
public DataIdentificator(Dictionary<string, int> MappingTable)
{
_mappingTable = MappingTable;
//DataTypes populieren. Dazu: einlesen, nach DT qualifier in temp. Liste speichern, damit neuen DIDT erzeugen und zur Liste hinzufügen
Initialize();
}
private void Initialize()
{
string _currentDataType;
DataTypes = new();
List<DataIdentifier> dataIdentifier = ReadDataIdentifierFromFile();
_currentDataType = dataIdentifier[0].DataType;
List<string> _identifierOfCurrentType = new();
foreach (DataIdentifier qualifier in dataIdentifier)
{
if (qualifier.DataType == _currentDataType)
{
_identifierOfCurrentType.Add(qualifier.Identifier);
if (qualifier == dataIdentifier[^1]) //letztes Element der Liste
{
DataIdType typeToBeAdded = new(_currentDataType, _identifierOfCurrentType);
DataTypes.Add(typeToBeAdded);
//_currentDataType = qualifier.DataType;
}
continue;
}
else
{
DataIdType typeToBeAdded = new(_currentDataType, _identifierOfCurrentType);
DataTypes.Add(typeToBeAdded);
_currentDataType = qualifier.DataType;
_identifierOfCurrentType.Clear();
_identifierOfCurrentType.Add(qualifier.Identifier);
}
}
}
public List<string> Identify(bool MustMatchAllQualifer = true)
{
List<string> winners = new();
foreach (DataIdType datatype in DataTypes)
{
foreach (string qualifier in datatype.Qualifiers)
{
if (_mappingTable.ContainsKey(qualifier))
{
datatype.AddFoundQualfier(qualifier);
}
}
}
if (MustMatchAllQualifer)
{
foreach (DataIdType dataType in DataTypes) //may return multiple winners
{
if (dataType.AllQualifierMatched)
{
winners.Add(dataType.DataType);
}
}
}
else //return the winner by highest score:
{
winners.Add(DataTypes.Aggregate((x, y) => x.Score > y.Score ? x : y).DataType.ToString());
}
//Plausibilty checkpoint:
//1. Remove "PL", "AccountType", "Submarket" from Winner-List, if detected datatype is "LSAG" or "Account".
//2. LSAG = Account + Contact --> when LSAG is a winner, remove "LSAG" and add "Account" and "Contact" to use their dedicated import methods.
//3. Remove any other winner, when winner is one of "PL", "AccountType", "Submarket" AND fields[].count = 2.
if (MustMatchAllQualifer == true && winners.Contains("LSAG"))
{
if (winners.Contains("ProductLine"))
{
_ = winners.Remove("ProductLine");
}
if (winners.Contains("AccountType"))
{
_ = winners.Remove("AccountType");
}
if (winners.Contains("SubMarket"))
{
_ = winners.Remove("SubMarket");
}
if (winners.Contains("Account"))
{
_ = winners.Remove("Account");
}
if (winners.Contains("Contact"))
{
_ = winners.Remove("Contact");
}
}
if (MustMatchAllQualifer == true && winners.Contains("Account"))
{
if (winners.Contains("ProductLine"))
{
_ = winners.Remove("ProductLine");
}
if (winners.Contains("AccountType"))
{
_ = winners.Remove("AccountType");
}
if (winners.Contains("SubMarket"))
{
_ = winners.Remove("SubMarket");
}
}
if (MustMatchAllQualifer == false && _mappingTable.Count == 2)
{
if (winners.Contains("ProductLine"))
{
winners.Clear();
winners.Add("ProductLine");
}
if (winners.Contains("AccountType"))
{
winners.Clear();
winners.Add("AccountType");
}
if (winners.Contains("SubMarket"))
{
winners.Clear();
winners.Add("SubMarket");
}
}
return winners;
}
public static List<DataIdentifier> ReadDataIdentifierFromFile()
{
List<DataIdentifier> result = new(50);
string fileInput = FileIO.ReadResource("DataIdentifier.txt");
string[] lines = fileInput.Split(Environment.NewLine);
foreach (string line in lines)
{
string[] fields;
DataIdentifier identifier = new();
fields = line.Split("|");
identifier.DataType = fields[0];
identifier.Identifier = fields[1];
result.Add(identifier);
}
return result;
}
}
}

@ -0,0 +1,8 @@
namespace Gremlin_BlazorServer.GremlinUtilities.GUClasses
{
public class DataIdentifier
{
public string DataType { get; set; }
public string Identifier { get; set; }
}
}

@ -0,0 +1,38 @@
AccountType|AccountTypeCode
AccountType|AccountTypeDescription
SubMarket|SubMarketCode
SubMarket|SubMarketDescription
ProductLine|ProductLineCode
ProductLine|ProductLineDescription
Product|ProductNumber
Product|ListPrice
Product|Weight
Product|BreakRangeFrom
LSAG|AccountName
LSAG|Street
LSAG|ZIP
LSAG|City
LSAG|PhoneNumber
LSAG|SAPAccountNumber
LSAG|AccountTypeCode
LSAG|SubMarketCode
LSAG|SAPContactNumber
LSAG|LastName
LSAG|MA_ProductInterests
Account|AccountName
Account|Street
Account|ZIP
Account|City
Account|PhoneNumber
Account|SAPAccountNumber
Account|AccountTypeCode
Account|SubMarketCode
Contact|LastName
Contact|SAPContactNumber
Contact|FirstName
Contact|Gender
CustomDescription|Heading
CustomDescription|ProductNumber
CustomDescription|OptionNumber
CustomDescription|DescriptionText
CustomDescription|CoverletterText

@ -0,0 +1,142 @@
sapaccountnumber|SAPAccountNumber
accountid|SAPAccountNumber
fcustomercd|SAPAccountNumber
accountname|AccountName
fcustomername|AccountName
zip|ZIP
postalcode|ZIP
fpostcode|ZIP
city|City
ftown|City
street|Street
faddress|Street
academictitle|AcademicTitle
title|AcademicTitle
ftitletext1|AcademicTitle
gender|Gender
fgender1|Gender
firstname|FirstName
ffirstname|FirstName
lastname|LastName
flastname|LastName
optinstatus|OptInStatus
optin|OptInStatus
femailopt|OptInStatus
email|EMail
workemail|EMail
fworkemail1|EMail
accountemail|EMail
emailbounced|EmailBounced
bouncedbackemail|EmailBounced
fbouncedback|EmailBounced
department|Department
fdepartment1|Department
room|Room
roomnumber|Room
froomnumber|Room
phonenumber|PhoneNumber
workphone|PhoneNumber
fworkphone1|PhoneNumber
faxnumber|FaxNumber
function|Function
ffunction|Function
sapcontactnumber|SAPContactNumber
contactid|SAPContactNumber
fcontactcd|SAPContactNumber
sapcontactcreationdate|SAPContactCreationDate
contactcreationdate|SAPContactCreationDate
fcreationdate|SAPContactCreationDate
mobilenumber|MobileNumber
mobilephone|MobileNumber
fmobilephone|MobileNumber
majobfunctions|MA_JobFunctions
jobfunction|MA_JobFunctions
fjobfunction|MA_JobFunctions
maproductinterests|MA_ProductInterests
productinterest|MA_ProductInterests
fproductinterest|MA_ProductInterests
maapplicationinterests|MA_ApplicationInterests
applicationinterest|MA_ApplicationInterests
fapplicationinterest|MA_ApplicationInterests
majoblevel|MA_JobLevel
joblevel|MA_JobLevel
fjoblevel|MA_JobLevel
macontactindustry|MA_ContactIndustry
contactindustry|MA_ContactIndustry
fcontactindustry|MA_ContactIndustry
macompetitiveibase|MA_CompetitiveIBase
competitiveibase|MA_CompetitiveIBase
fcompetativeibase|MA_CompetitiveIBase
submarketcode|SubMarketCode
submarketcodes|SubMarketCode
fsubmarketcd|SubMarketCode
accountsubmarketcode|SubMarketCode
accounttypecode|AccountTypeCode
customertypecode|AccountTypeCode
fcustomertypecd|AccountTypeCode
accounttype|AccountTypeCode
accounttypes|AccountTypeCode
accountphonenumber|AccountPhoneNumber
phone|AccountPhoneNumber
fphone|AccountPhoneNumber
accountcreatedinsapon|AccountCreatedInSAPOn
accountcreatedon|AccountCreatedInSAPOn
fcreatedon|AccountCreatedInSAPOn
sapcontactmodifieddate|SAPContactModifiedDate
contactchangedon|SAPContactModifiedDate
fcontactchangedon|SAPContactModifiedDate
nophonecalls|NoPhoneCalls
notelephonecalls|NoPhoneCalls
fnotelephonecalls|NoPhoneCalls
nohardcopymailing|NoHardcopyMailing
fnohardcopymailing|NoHardcopyMailing
accounttypedescription|AccountTypeDescription
submarketdescription|SubMarketDescription
submarketdescriptions|SubMarketDescription
productlineabbreviation|ProductLineCode
productlineabbreviations|ProductLineCode
productlinedescription|ProductLineDescription
productlinedescriptions|ProductLineDescription
productNumber|ProductNumber
partnumber|ProductNumber
produktnummer|ProductNumber
optionnumber|OptionNumber
option|OptionNumber
sapshortdescription|SapShortDescription
description|SapShortDescription
listprice|ListPrice
currentmonthprice(eur)|ListPrice
breakrangefrom|BreakRangeFrom
breaksrangefrom|BreakRangeFrom
breakrangeto|BreakRangeTo
breaksrangeto|BreakRangeTo
productline|ProductLineCode
weight|Weight
airpackagedweight|Weight
introductiondate|IntroductionDate
saplongdescription|SapLongDescription
longdescription|SapLongDescription
status|ProductStatus
datastatus|Datastatus
weightunit|WeightUnit
airpackagedunit|WeightUnit
previousmonthprice(eur)|PreviousMonthPrice
warranty|Warranty
phcode|PHCode
phdescription|PHDescription
countryofmanufacturing|CountryOfManufacturing
eccl|ECCL
m41|M41
firstsuppliercode|FirstSupplierCode
harmonizedtarifschedule|HarmonizedTarifSchedule
hazardousgoodsflag|HazardousGoodsFlag
orderinstructions|OrderInstructions
endofproductiondate|EndOfProductionDate
endofsupportdate|EndOfSupportDate
nonagilentprodukt|Supplier
überschrift|Heading
ueberschrift|Heading
heading|Heading
produktbeschreibung|DescriptionText
anschreiben|CoverletterText
hinweise|Notes

@ -0,0 +1,103 @@
using Gremlin_BlazorServer.ViewModels;
using System;
using System.Diagnostics;
using System.IO;
namespace Gremlin_BlazorServer.GremlinUtilities
{
internal class PDFHandler
{
// public static bool CreatePDF(QuoteViewModel quoteVM)
// {
// //Copy images to quotePath
// try
// {
// if (quoteVM.QuotePath is "" or null)
// {
// File.WriteAllBytes("agilentLogo.png", Properties.Resources.agilentLogo);
// File.WriteAllBytes("signWoitschetzki.png", Properties.Resources.signWoitschetzki);
// }
// else
// {
// File.WriteAllBytes($"{quoteVM.QuotePath}agilentLogo.png", Properties.Resources.agilentLogo);
// File.WriteAllBytes($"{quoteVM.QuotePath}signWoitschetzki.png", Properties.Resources.signWoitschetzki);
// }
// //Create PDF twice
// RunningPDFLaTeX(quoteVM, 2);
// RemoveTempFiles(quoteVM.QuotePath);
// return true;
// }
// catch (Exception ex)
// {
// ErrorHandler.ShowErrorInMessageBox(ex);
// return false;
// }
// }
public static void RemoveTempFiles(string quotePath)
{
DirectoryInfo directoryInfo = new(quotePath);
foreach (FileInfo file in directoryInfo.EnumerateFiles())
{
if (file.Extension is ".aux" or ".out" or ".log") // or ".png") #let pngs left
{
try
{
file.Delete();
//Console.WriteLine($"{file.FullName} wurde gelöscht.");
}
catch (Exception ex)
{
ErrorHandler.ShowErrorInMessageBox(ex);
}
}
}
}
// private static void RunningPDFLaTeX(QuoteViewModel quoteVM, int runs)
// {
// for (int i = 0; i < runs; i++)
// {
// using (Process process = new())
// {
// process.StartInfo.WorkingDirectory = quoteVM.QuotePath;
// process.StartInfo.FileName = "pdflatex";
// process.StartInfo.Arguments = quoteVM.QuoteNumber;
// process.StartInfo.UseShellExecute = true;
// try
// {
// _ = process.Start();
// }
// catch (Exception ex)
// {
// ErrorHandler.ShowErrorInMessageBox(ex);
// }
// process.WaitForExit();
// }
// }
// }
// public static bool OpenPDF(QuoteViewModel quoteVM)
// {
// using (Process process = new())
// {
// process.StartInfo.WorkingDirectory = quoteVM.QuotePath;
// process.StartInfo.FileName = @"C:\Program Files\Okular\bin\okular.exe";
// process.StartInfo.Arguments = $"{quoteVM.QuoteNumber}.pdf";
// try
// {
// return process.Start();
// }
// catch (Exception ex)
// {
// ErrorHandler.ShowErrorInMessageBox(ex);
// return false;
// }
// }
// }
}
}

@ -0,0 +1,372 @@
using Gremlin_BlazorServer.GremlinData.EntityClasses;
using Gremlin_BlazorServer.Models;
using Gremlin_BlazorServer.ViewModels;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using static Gremlin_BlazorServer.GremlinData.EntityClasses.Enums;
namespace Gremlin_BlazorServer.GremlinUtilities
{
internal class TexHandler
{
// internal static bool CreateTex(QuoteViewModel quoteVM)
// {
// StringBuilder texStringBuilder = CreateTexFile(quoteVM);
// if (quoteVM.QuotePath is "" or null)
// {
// WriteTextToFile(texStringBuilder, $"{quoteVM.QuoteNumber}.tex");
// }
// else
// {
// WriteTextToFile(texStringBuilder, $"{quoteVM.QuotePath}{quoteVM.QuoteNumber}.tex");
// }
// return texStringBuilder.Length > 0;
// }
private static void WriteTextToFile(StringBuilder texFile, string datei)
{
using StreamWriter writer = new(datei, false, Encoding.UTF8);
{
writer.WriteLine(texFile.ToString());
}
}
public static StringBuilder CreateBriefkopf(ContactViewModel contactVM, bool tex = false)
{
StringBuilder briefkopf = new();
_ = contactVM.Gender == Enums.Gender.Male
? briefkopf.AppendLine($"Herr {contactVM.FirstName} {contactVM.LastName}")
: briefkopf.AppendLine($"Frau {contactVM.FirstName} {contactVM.LastName}");
if (tex)
{
_ = briefkopf.AppendLine($"\\\\");
}
string AccountName = contactVM.GetAccountName();
//AccountNamen mit "&" im Namen abfangen
if (tex && AccountName.Contains('&'))
{
string[] accountNameSplit = AccountName.Split("&"); //.Replace?
AccountName = "";
for (int i = 0; i < accountNameSplit.Length; i++)
{
AccountName += i < accountNameSplit.Length - 1
? accountNameSplit[i] + "\\&"
: accountNameSplit[i];
}
}
_ = briefkopf.AppendLine($"{AccountName}");
if (tex) { _ = briefkopf.AppendLine($"\\\\"); }
_ = briefkopf.AppendLine($"{contactVM.AccountStreet}");
if (tex) { _ = briefkopf.AppendLine($"\\\\"); }
_ = briefkopf.AppendLine($"{contactVM.AccountZIP} {contactVM.AccountCity}");
if (tex) { _ = briefkopf.AppendLine($"\\\\"); }
return briefkopf;
}
// private static StringBuilder CreateTexFile(QuoteViewModel quoteVM)
// {
// string rand = 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}}}}");
// _ = texFile.AppendLine($"\\rohead{{{quoteVM.QuoteNumber}}}");
// _ = 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}");
// _ = quoteVM.Preisinformation
// ? texFile.AppendLine("\n\\colorbox{AgilentBlau}{\\textcolor{white}{\\textsc{\\Huge{Preisinformation}}}}\n\\end{flushright}\n\\begin{tabular}{p{0.4\\hsize}p{0.6\\hsize}}")
// : 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("\n &\n\\multirow{4}{*}{"
// + "\n\\begin{tabular}{|ll|}"
// + "\n\\hline");
// _ = texFile.AppendLine($"\\textbf{{Angebotsnummer:}}&{quoteVM.QuoteNumber}\\\\");
// _ = texFile.Append($"Angebotdatum:&\\today\\\\\nAngebotsgültigkeit:&{quoteVM.Validity} Tage\\\\");
// _ = texFile.AppendLine($"\\textbf{{Ansprechpartner:}}&{RUSettingModel.GetSettingValue(Properties.Settings.Default.userSettingID, "userName")}\\\\");
// _ = texFile.AppendLine($"Telefon: &{RUSettingModel.GetSettingValue(Properties.Settings.Default.userSettingID, "userPhone")}\\\\");
// _ = texFile.AppendLine($"Mobil:&{RUSettingModel.GetSettingValue(Properties.Settings.Default.userSettingID, "userMobile")}\\\\");
// _ = texFile.AppendLine($"E-Mail:&\\href{{mailto:{RUSettingModel.GetSettingValue(Properties.Settings.Default.userSettingID, "userMail")}}}{{{RUSettingModel.GetSettingValue(Properties.Settings.Default.userSettingID, "userMail")}}}\\\\");
// _ = texFile.AppendLine("\\textbf{Auftragsannahme:}&\\href{mailto:salesservices\\_germany@agilent.com}{salesservices\\_germany@agilent.com}\\\\\n"
// + "\\hline\n\\end{tabular}\n}\\\\");
// if (quoteVM.Recipient != null)
// {
// _ = texFile.Append(CreateBriefkopf(quoteVM.Recipient, true));
// }
// _ = texFile.AppendLine("&\\\\\n&\\\\\n\\end{tabular}\n\\vspace{1cm}\\par ");
// //Anrede
// _ = quoteVM.Recipient.Gender == Gender.Male
// ? texFile.AppendLine($"Sehr geehrter Herr {quoteVM.Recipient.LastName},\\par ")
// : texFile.AppendLine($"Sehr geehrte Frau {quoteVM.Recipient.LastName},\\par ");
// //Anschreiben
// _ = texFile.AppendLine(CreateCoverletter(quoteVM));
// //RB-Disclaimer
// if (quoteVM.QuoteContainsRB)
// {
// _ = texFile.AppendLine(CreateRBDisclaimer(quoteVM));
// }
// //Tabelle
// _ = texFile.AppendLine("\\begin{center}");
// _ = texFile.AppendLine("\\begin{longtable}");
// if (quoteVM.SinglePrices == true)
// {
// if (quoteVM.ShowDiscounts == 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 (quoteVM.ShowDiscounts == 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");
// }
// }
// else
// {
// //ohne Einzelpreise
// _ = texFile.AppendLine("{| cp{0.83\\textwidth} c |} \\hline");
// _ = texFile.AppendLine(@"\textbf{\#} & \textbf{Produktbeschreibung} (Produktnummer) & \textbf{Menge}\\ \hline \endhead");
// }
// foreach (LineItemViewModel lI in quoteVM.LineItemsVM)
// {
// string lineItemTex = "";
// if (quoteVM.SinglePrices == true)
// {
// if (quoteVM.ShowDiscounts == false)
// {
// //mit Einzelpreisen
// lineItemTex = lI.OptionNumber != ""
// ? $"{lI.Position} &\\textbf{{{lI.CustomDescriptionVM.Heading}}} ({lI.ProductNumber}\\#{lI.OptionNumber})\\newline {lI.CustomDescriptionVM.DescriptionText}&{lI.Amount}&\\SI{{{lI.CalcTotalNet}}}{{\\sieuro}}\\\\"
// : $"{lI.Position} &\\textbf{{{lI.CustomDescriptionVM.Heading}}} ({lI.ProductNumber})\\newline {lI.CustomDescriptionVM.DescriptionText}&{lI.Amount}&\\SI{{{lI.CalcTotalNet}}}{{\\sieuro}}\\\\";
// }
// else if (quoteVM.ShowDiscounts == true)
// {
// //mit Einzelpreisen und Discounts
// lineItemTex = lI.OptionNumber != ""
// ? $"{lI.Position} &\\textbf{{{lI.CustomDescriptionVM.Heading}}} ({lI.ProductNumber}\\#{lI.OptionNumber})\\newline {lI.CustomDescriptionVM.DescriptionText}\\newline Listenpreis: \\SI{{{lI.ListPrice}}}{{\\sieuro}}&{lI.Amount}&\\SI{{{lI.TotalDiscount}}}{{\\%}}&\\SI{{{lI.CalcTotalNet}}}{{\\sieuro}}\\\\"
// : $"{lI.Position} &\\textbf{{{lI.CustomDescriptionVM.Heading}}} ({lI.ProductNumber})\\newline {lI.CustomDescriptionVM.DescriptionText}\\newline Listenpreis: \\SI{{{lI.ListPrice}}}{{\\sieuro}}&{lI.Amount}&\\SI{{{lI.TotalDiscount}}}{{\\%}}&\\SI{{{lI.CalcTotalNet}}}{{\\sieuro}}\\\\";
// }
// }
// else if (quoteVM.SinglePrices == false)
// {
// //ohne Einzelpreise
// lineItemTex = lI.OptionNumber != ""
// ? $"{lI.Position} &\\textbf{{{lI.CustomDescriptionVM.Heading}}} ({lI.ProductNumber}\\#{lI.OptionNumber})\\newline {lI.CustomDescriptionVM.DescriptionText}&{lI.Amount}\\\\"
// : $"{lI.Position} &\\textbf{{{lI.CustomDescriptionVM.Heading}}} ({lI.ProductNumber})\\newline {lI.CustomDescriptionVM.DescriptionText}&{lI.Amount}\\\\";
// }
// _ = 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");
// //Summe netto
// _ = texFile.AppendLine($"\\textbf{{Summe netto}} & \\SI{{{quoteVM.TotalNet}}}{{\\sieuro}}\\\\");
// //Frachtkosten
// _ = texFile.AppendLine($"\\textbf{{Versand und Bereitstellungskosten ({quoteVM.Freight}\\%)}} & \\SI{{{quoteVM.TotalFreightOnly}}}{{\\sieuro}}\\\\");
// //Gesamtsumme netto
// _ = texFile.AppendLine($"\\textbf{{Gesamtsumme netto}} & \\SI{{{quoteVM.TotalFreight}}}{{\\sieuro}}\\\\");
// //mit Mehrwertsteuer
// if (quoteVM.ShowBrutto == true)
// {
// _ = texFile.AppendLine($"\\textbf{{Umsatzsteuer ({quoteVM.VAT}\\%)}} & \\SI{{{quoteVM.TotalVAT}}}{{\\sieuro}}\\\\");
// _ = texFile.AppendLine($"\\textbf{{Gesamtsumme brutto}} & \\SI{{{quoteVM.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 {quoteVM.Warranty} Monate.\n");
// //3PP-Disclaimer
// if (quoteVM.QuoteContains3PP)
// {
// _ = texFile.AppendLine(Create3PPDisclaimer(quoteVM));
// }
// _ = 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(QuoteViewModel quoteVM)
// {
// Random r = new();
// 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<LineItemViewModel> lineItemsWithRB = quoteVM.LineItemsVM.Where(lI => lI.ProductLine == "RB").ToList();
// rbDisclaimer += "\\begin{center}\n\\begin{tabular}{clc}\n";
// rbDisclaimer += "\\textbf{Modul} & \\textbf{Beschreibung} &\\textbf{Bestand}\\\\ \\hline \n";
// foreach (LineItemViewModel lineItemWithRB in lineItemsWithRB)
// {
// int rbcount = r.Next(20) - 5; //Get count of RB?
// rbDisclaimer += $"{lineItemWithRB.ProductNumber} & {lineItemWithRB.CustomDescriptionVM.Heading} & {rbcount}\\\\ \n";
// }
// rbDisclaimer += "\\end{tabular}\n\\end{center}\n";
// return rbDisclaimer;
// }
// private static string Create3PPDisclaimer(QuoteViewModel quoteVM)
// {
// 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<LineItemViewModel> lineItemsWith3PP = quoteVM.LineItemsVM.Where(lI => lI.ProductLine == "3PP").ToList();
// for (int i = 0; i < lineItemsWith3PP.Count; i++)
// {
// _ = i < lineItemsWith3PP.Count - 1
// ? dreipp += $"{lineItemsWith3PP[i].ProductNumber}, "
// : 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 += "\\textbf{Hersteller:}";
// //supllier3PP
// return dreipp;
// }
// private static string GetCoverletterRow(LineItemViewModel lineItemVM)
// {
// return lineItemVM.CustomDescriptionVM.CoverletterText is null or ""
// ? $"\\item {lineItemVM.CustomDescriptionVM.Heading} (\\#{lineItemVM.Position})\n"
// : $"\\item {lineItemVM.CustomDescriptionVM.CoverletterText} (\\#{lineItemVM.Position})\n";
// }
// private static string CreateCoverletter(QuoteViewModel quoteVM)
// {
// bool subitem = false;
// string coverLetter = $"nachfolgend erhalten Sie Ihr gewünschtes Angebot über {quoteVM.QuoteType}.\\\\\n"
// + "Es umfasst im Einzelnen:\n"
// + "\\begin{itemize}\n";
// foreach (LineItemViewModel lineItemVM in quoteVM.LineItemsVM)
// {
// if (lineItemVM.OptionNumber == "")
// {
// //Hauptitem
// if (subitem)
// {
// //vorheriges Subitem schließen
// coverLetter += "\\end{itemize}\n";
// subitem = false;
// }
// }
// else
// {
// if (!subitem)
// {
// //neues Subitem
// subitem = true;
// coverLetter += "\\begin{itemize}\n";
// }
// }
// coverLetter += GetCoverletterRow(lineItemVM);
// }
// 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";
// return coverLetter;
// }
// public static string Replace(string text)
// {
// if (text == null)
// {
// return null;
// }
// else
// {
// text = text.Contains('&') ? text.Replace("&", "\\&") : text;
// text = text.Contains("<Shift-Enter>") ? text.Replace("<Shift-Enter>", "\\newline ") : text;
// return text;
// }
// }
}
}

@ -9,7 +9,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
<PackageReference Include="morelinq" Version="3.3.2" />
<PackageReference Include="MySqlConnector" Version="2.2.0" />
</ItemGroup>

@ -1,6 +0,0 @@
namespace Gremlin_BlazorServer.Models
{
public class Account
{
}
}

@ -0,0 +1,54 @@
using Gremlin_BlazorServer.GremlinData.EntityClasses;
using Gremlin_BlazorServer.ViewModels;
// using System.Windows.Data;
namespace Gremlin_BlazorServer.Models
{
public class ContactModel
{
public static ContactViewModel ConvertContactToContactVM(Contact contact)
{
if (contact.Account != null)
{
ContactViewModel contactVM = new()
{
ContactID = contact.ContactId,
Gender = (Enums.Gender)contact.Gender,
LastName = contact.LastName,
FirstName = contact.FirstName,
EMail = contact.EMail,
AccountName = contact.Account.AccountName,
AccountStreet = contact.Account.Street,
AccountZIP = contact.Account.ZIP,
AccountCity = contact.Account.City,
AccountTypeCode = contact.Account.AccountType.AccountTypeCode
};
return contactVM;
}
else
{
ErrorHandler.ShowErrorMessage($"Kontakt {contact.LastName} hat keinen Account!");
return null;
}
}
public static ContactViewModel ConvertObjectToContactVM(object selectedItem)
{
ContactViewModel selectedContact = new();
if (selectedItem != CollectionView.NewItemPlaceholder)
{
//TryCast
selectedContact = selectedItem as ContactViewModel;
//if failed == null
if (selectedContact == null)
{
return default;
}
}
return selectedContact;
}
}
}

@ -0,0 +1,62 @@
using Gremlin_BlazorServer.GremlinData.DBClasses;
using Gremlin_BlazorServer.GremlinData.EntityClasses;
using Gremlin_BlazorServer.ViewModels;
// using Gremlin_BlazorServer.Views;
using System;
using System.Collections.Generic;
namespace Gremlin_BlazorServer.Models
{
public class CustomDescriptionModel
{
public static CustomDescription SearchForProducts(LineItem angebot, List<CustomDescription> customDescriptions)
{
List<CustomDescription> resultCustomDescriptions = customDescriptions.FindAll(customDescription => customDescription.ProductNumber == angebot.ProductNumber);
return resultCustomDescriptions.Find(customDescription => customDescription.OptionNumber == angebot.OptionNumber);
}
// public static bool CreateNewCustomDescription(CustomDescriptionViewModel customDescriptionVM, LineItemViewModel lineItemVM)
// {
// if (lineItemVM.OptionNumber == "")
// {
// lineItemVM.OptionNumber = null;
// }
// CustomDescription customDescription = new()
// {
// AccountId = 1,
// ProductNumber = lineItemVM.ProductNumber,
// OptionNumber = lineItemVM.OptionNumber,
// DescriptionText = customDescriptionVM.DescriptionText,
// Heading = customDescriptionVM.Heading,
// CoverletterText = customDescriptionVM.Heading,
// DataCreationDate = DateTime.Now,
// DataModificationDate = DateTime.Now,
// DataValidFrom = DateTime.Now,
// DataValidUntil = DateTime.MaxValue,
// DataVersionNumber = 1,
// DataModificationByUser = "Gremlin",
// DataStatus = "Active",
// Notes = "Description has to be edited manually!"
// };
// CheckNewCustomDescription checkNewCustomDescription = new(lineItemVM, customDescriptionVM);
// if (checkNewCustomDescription.ShowDialog() == true)
// {
// customDescription.Heading = checkNewCustomDescription.CustomDescriptionVM.Heading;
// customDescription.CoverletterText = checkNewCustomDescription.CustomDescriptionVM.CoverletterText;
// customDescription.DescriptionText = checkNewCustomDescription.CustomDescriptionVM.DescriptionText;
// using (GremlinContext gremlinContext = new())
// {
// _ = gremlinContext.Add(customDescription);
// _ = gremlinContext.SaveChanges();
// return true;
// }
// }
// return false;
// }
}
}

@ -0,0 +1,136 @@
using Gremlin_BlazorServer.GremlinData.EntityClasses;
using Gremlin_BlazorServer.GremlinUtilities;
using Gremlin_BlazorServer.ViewModels;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
namespace Gremlin_BlazorServer.Models
{
public class LineItemModel
{
// public static IList<LineItem> ConvertToLineItems(ObservableCollection<LineItemViewModel> lineItemsVM)
// {
// IList<LineItem> lineItems = new List<LineItem>();
// foreach (LineItemViewModel lineItemViewModel in lineItemsVM)
// {
// LineItem lineItem = ConvertToLineItem(lineItemViewModel);
// lineItems.Add(lineItem);
// }
// return lineItems;
// }
// public static LineItem ConvertToLineItem(LineItemViewModel lineItemViewModel)
// {
// LineItem lineItem = new()
// {
// ProductNumber = lineItemViewModel.ProductNumber,
// OptionNumber = lineItemViewModel.OptionNumber,
// ProductLine = lineItemViewModel.ProductLine,
// ListPrice = lineItemViewModel.ListPrice,
// SapShortDescription = lineItemViewModel.SapShortDescription,
// TotalDiscount = lineItemViewModel.TotalDiscount,
// Total = lineItemViewModel.CalcTotalNet,
// DataModificationByUser = "Gremlin",
// DataStatus = "Active"
// };
// return lineItem;
// }
// public static ObservableCollection<LineItemViewModel> ReadLineItemsFromClipboard(QuoteViewModel quoteVM)
// {
// if (Clipboard.GetText() != "")
// {
// string clipboard = Clipboard.GetText();
// //Angebot in eine TSV-File schreiben
// FileIO.WriteClipboardToTSV(clipboard, quoteVM);
// //Zeilen aufteilen
// IEnumerable<string> clipboardLines = clipboard.Split(Environment.NewLine.ToCharArray());
// List<string[]> clipboardList = new();
// foreach (string clipboardLine in clipboardLines)
// {
// if (clipboardLine != "")
// {
// //Nach Trennzeichen trennen
// string[] clipboardLineSplit = clipboardLine.Split('\t');
// clipboardList.Add(clipboardLineSplit);
// }
// }
// return ParseClipboardList(clipboardList);
// }
// else
// {
// _ = MessageBox.Show("Clipboard ist leer!");
// return null;
// }
// }
// public static ObservableCollection<LineItemViewModel> ParseClipboardList(IEnumerable<string[]> lineItemStrings)
// {
// ObservableCollection<LineItemViewModel> lineItems = new();
// int countError = 0;
// int countEmpty = 0;
// foreach (string[] lineItemString in lineItemStrings)
// {
// //Anzahl an Spalten entspricht Clipboard
// if (lineItemString.Length == 19)
// {
// //Header ignorieren
// if (lineItemString[0] == "#")
// {
// countEmpty++;
// continue;
// }
// //Dateiinhalt in Klasse schreiben
// LineItemViewModel lineItem = new()
// {
// Position = ushort.Parse(lineItemString[0]),
// ProductNumber = lineItemString[1],
// OptionNumber = lineItemString[2],
// ProductLine = lineItemString[3],
// SapShortDescription = lineItemString[4],
// Amount = ushort.Parse(lineItemString[5]),
// ListPrice = decimal.Parse(lineItemString[6]),
// TotalDiscount = decimal.Parse(lineItemString[9])
// };
// //Preise einlesen
// //lineItem.NetPrice = decimal.Parse(lineItemString[10]);
// //lineItem.TotalNet = decimal.Parse(lineItemString[11]);
// //Preise selbst berechnen
// lineItem.CalcNetPrice = lineItem.ListPrice * (100 - lineItem.TotalDiscount) / 100;
// lineItem.CalcTotalNet = lineItem.CalcNetPrice * lineItem.Amount;
// //nicht genutzte Felder
// //lineItem.SalesDiscount = decimal.Parse(lineItemString[12]);
// //lineItem.ContractualDiscount = decimal.Parse(lineItemString[13]);
// //lineItem.PromotionalDiscount = decimal.Parse(lineItemString[14]);
// //lineItem.DemoDiscount = decimal.Parse(lineItemString[15]);
// lineItem.CustomDescriptionVM = CustomDescriptionViewModel.GetCustomDescription(lineItem);
// lineItems.Add(lineItem);
// }
// else
// {
// _ = MessageBox.Show("Angebot konnte nicht eingelesen werden!");
// countError++;
// continue;
// }
// }
// return lineItems;
// }
}
}

@ -0,0 +1,19 @@
using Gremlin_BlazorServer.GremlinData.EntityClasses;
using System.Collections.Generic;
namespace Gremlin_BlazorServer.Models
{
internal class ProductModel
{
public static Product SearchForProduct(LineItem lineItem, List<Product> productList)
{
List<Product> resultsProduct = productList.FindAll(pL => pL.ProductNumber == lineItem.ProductNumber);
return resultsProduct.Find(pL => pL.OptionNumber == lineItem.OptionNumber);
}
public static List<Product> SearchForProducts(List<Product> productList, string search)
{
return productList.FindAll(pL => pL.ProductNumber == search);
}
}
}

@ -0,0 +1,47 @@
using Gremlin_BlazorServer.GremlinData.DBClasses;
using Gremlin_BlazorServer.GremlinData.EntityClasses;
using Gremlin_BlazorServer.ViewModels;
using System;
namespace Gremlin_BlazorServer.Models
{
public class QuoteModel
{
// public static bool WriteToDB(QuoteViewModel quoteVM)
// {
// Quote quote = new()
// {
// ContactId = quoteVM.Recipient.ContactID,
// QuotationNumber = quoteVM.QuoteNumber,
// QuotationDate = DateTime.Now,
// ValidUntil = DateTime.Now.AddDays(quoteVM.Validity),
// ValidFor = (byte)quoteVM.Validity,
// TotalListprice = quoteVM.TotalListprice,
// //quote.TotalDiscount =
// TotalNet = quoteVM.TotalNet,
// VAT = Convert.ToSingle(quoteVM.VAT),
// TotalGross = quoteVM.TotalGross,
// QuoteContains3PP = quoteVM.QuoteContains3PP,
// QuoteContainsRB = quoteVM.QuoteContainsRB,
// DataModificationByUser = "Gremlin",
// LineItems = LineItemModel.ConvertToLineItems(quoteVM.LineItemsVM),
// DataStatus = "Active"
// };
// try
// {
// using (GremlinContext gremlinContext = new())
// {
// _ = gremlinContext.Add(quote);
// _ = gremlinContext.SaveChanges();
// }
// return true;
// }
// catch (Exception ex)
// {
// ErrorHandler.ShowErrorInMessageBox(ex);
// return false;
// }
// }
}
}

@ -1,6 +1,7 @@
@page "/contacts"
@using Gremlin_BlazorServer.Services;
@using Gremlin_BlazorServer.Models;
@using Gremlin_BlazorServer.ViewModels;
<PageTitle>Contacts</PageTitle>
@ -34,7 +35,7 @@ else
</tr>
</thead>
<tbody>
@foreach (Contact contact in filteredContacts)
@foreach (ContactViewModel contact in filteredContacts)
{
<tr>
<td>@contact.ContactId</td>
@ -51,8 +52,8 @@ else
@code {
public string searchContact = "";
private List<Contact> allContacts = new();
private List<Contact> filteredContacts = new();
private List<ContactViewModel> allContacts = new();
private List<ContactViewModel> filteredContacts = new();
protected override async Task OnInitializedAsync()
{

@ -1,11 +1,8 @@
using Gremlin_BlazorServer.Data;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
var app = builder.Build();

@ -1,4 +1,4 @@
using Gremlin_BlazorServer.Models;
using Gremlin_BlazorServer.ViewModels;
using MySqlConnector;
using System.Data;
using System.Diagnostics;
@ -9,9 +9,9 @@ namespace Gremlin_BlazorServer.Services
{
private static string ConnectionString => ($"Server=woitschetzki.de;Database=regulus;User ID=root;Password=lungretter1");
public static async Task<List<Contact>> GetContactsFromDb(string searchContact)
public static async Task<List<ContactViewModel>> GetContactsFromDb(string searchContact)
{
List<Contact> contacts = new();
List<ContactViewModel> contacts = new();
DataTable dataTable = new();
MySqlConnection connection = new(ConnectionString);
@ -21,7 +21,7 @@ namespace Gremlin_BlazorServer.Services
foreach (DataRow row in dataTable.Rows)
{
Contact contact = new(
ContactViewModel contact = new(
Convert.ToInt32(row["ContactId"]),
Convert.ToInt32(row["AccountId"]),
(string)row["FirstName"],

@ -0,0 +1,6 @@
namespace Gremlin_BlazorServer.ViewModels
{
public class AccountViewModel
{
}
}

@ -1,15 +1,16 @@
namespace Gremlin_BlazorServer.Models
using Gremlin_BlazorServer.GremlinData.EntityClasses;
namespace Gremlin_BlazorServer.ViewModels
{
public class Contact
public class ContactViewModel
{
public int ContactId { get; set; }
public int AccountId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Gender { get; set; }
public Enums.Gender Gender { get; set; }
public string EMail { get; set; }
public Contact(int contactId, int accountId, string firstName, string lastName, int gender, string eMail)
public ContactViewModel(int contactId, int accountId, string firstName, string lastName, Enums.Gender gender, string eMail)
{
ContactId = contactId;
AccountId = accountId; //Account.GetAccount(accountId);
@ -18,5 +19,10 @@
Gender = gender;
EMail = eMail ?? throw new ArgumentNullException(nameof(eMail));
}
public static string GetAccountName()
{
return AccountId.ToString();
}
}
}