pull/3/head
Sascha 2023-09-11 10:02:28 +07:00
parent 75199cf93e
commit 785ef43396
11 changed files with 85 additions and 63 deletions

@ -1,19 +1,10 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Dockerfile" type="docker-deploy" factoryName="dockerfile" server-name="oregon">
<configuration default="false" name="dockerfile@server0" type="docker-deploy" factoryName="dockerfile" server-name="server0">
<deployment type="dockerfile">
<settings>
<option name="imageTag" value="dev" />
<option name="attachToContainerNeeded" value="true" />
<option name="containerName" value="gremlin_blazorserver" />
<option name="portBindings">
<list>
<DockerPortBindingImpl>
<option name="containerPort" value="5000" />
<option name="hostPort" value="5000" />
</DockerPortBindingImpl>
</list>
</option>
<option name="publishAllPorts" value="true" />
<option name="sourceFilePath" value="Dockerfile" />
</settings>
</deployment>

@ -2,8 +2,8 @@
FROM mcr.microsoft.com/dotnet/nightly/aspnet:8.0-preview AS base
WORKDIR /app
FROM mcr.microsoft.com/dotnet/nightly/runtime:8.0-preview AS run
EXPOSE 5000
FROM mcr.microsoft.com/dotnet/nightly/runtime:8.0-preview AS runtime
EXPOSE 8080
FROM mcr.microsoft.com/dotnet/nightly/sdk:8.0-preview AS build
WORKDIR /src
@ -13,7 +13,7 @@ COPY . .
WORKDIR "/src/Gremlin_BlazorServer"
RUN dotnet build "Gremlin_BlazorServer.csproj" -c Release -o /app/build
FROM run AS run
FROM runtime AS run
RUN dotnet dev-certs https
RUN dotnet dev-certs https --trust

@ -42,7 +42,7 @@ public class Quote : IMetadata {
public string? QuoteDescription { get; set; } = "Agilent Instrument";
public string? Tex { get; set; }
public string? Description { get; set; }
public string Path { get; set; } = HostingService.GetPath();
public string Path { get; set; } = HostingService.GetQuotePath();
//new properties

@ -96,7 +96,7 @@ public partial class QuoteAdd {
private async Task<Quote> GenerateQuoteFromString(Quote q, Contact r, string fileContent) {
q = ReadLineItems(q, r, fileContent);
if (q.LineItems.Count == 0) return q;
if (r.Account is not null) q.Path = HostingService.GetPath(q, r) ?? "Path not found!";
if (r.Account is not null) q.Path = HostingService.GetQuotePath(q, r) ?? "Path not found!";
FileService.WriteQuoteToTsv(fileContent, q);
q = await GetCustomDescriptionsForLineItems(q);
return q;

@ -48,7 +48,7 @@ builder.Services.AddControllersWithViews();
builder.WebHost.UseWebRoot("wwwroot");
builder.WebHost.UseStaticWebAssets();
builder.WebHost.UseUrls("https://*:5000");
// builder.WebHost.UseUrls("http://*:5000");
WebApplication app = builder.Build();
@ -59,7 +59,7 @@ if (!app.Environment.IsDevelopment()) {
_ = app.UseHsts();
}
app.UseHttpsRedirection();
//app.UseHttpsRedirection();
app.UseStaticFiles();
@ -73,4 +73,4 @@ app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();
app.Run();

@ -6,18 +6,15 @@ public static class HostingService {
// private static IWebHostEnvironment hostingEnvironment;
private static readonly HttpContextAccessor accessor = new();
private static IWebHostEnvironment WebEnv() {
return accessor.HttpContext.RequestServices.GetRequiredService<IWebHostEnvironment>();
}
private static IWebHostEnvironment WebEnv() => accessor.HttpContext?.RequestServices.GetRequiredService<IWebHostEnvironment>() ?? throw new InvalidOperationException();
// public HostingService(IWebHostEnvironment newHostingEnvironment) => hostingEnvironment = newHostingEnvironment;
public static string GetPath() {
return Path.Combine(WebEnv().WebRootPath, "quotes");
}
public static string GetImgPath() => Path.Combine(WebEnv().WebRootPath, "img");
public static string GetQuotePath() => Path.Combine(WebEnv().WebRootPath, "quotes");
public static string? GetPath(Quote quote, Contact recipient) {
if (recipient.Account.AccountName is null || quote.Description is null) {
public static string? GetQuotePath(Quote quote, Contact recipient) {
if (recipient.Account?.AccountName is null || quote.Description is null) {
Console.WriteLine("Quote.Path not setable! No acount or desciption in the quote...");
return null;
}
@ -29,7 +26,7 @@ public static class HostingService {
}
public static string? GetPdfUrl(Quote quote, Contact recipient) {
if (quote.QuotationNumber is null || recipient.Account.AccountName is null || quote.Description is null) {
if (quote.QuotationNumber is null || recipient.Account?.AccountName is null || quote.Description is null) {
Console.WriteLine("No path, account, description or quotation number in the quote!");
return null;
}

@ -5,12 +5,11 @@ namespace Gremlin_BlazorServer.Services;
internal abstract class PdfService {
public static async Task<bool> CreatePdf(Quote quote) {
if (quote.Path == null) return false;
//Copy images to quotePath
try {
File.Copy(Path.Combine("img", "agilentLogo.png"), Path.Combine(quote.Path, "agilentLogo.png"), true);
File.Copy(Path.Combine("img", "signWoitschetzki.png"), Path.Combine(quote.Path, "signWoitschetzki.png"), true);
string path = HostingService.GetImgPath();
File.Copy(Path.Combine(path, "agilentLogo.png"), Path.Combine(quote.Path, "agilentLogo.png"), true);
File.Copy(Path.Combine(path, "signWoitschetzki.png"), Path.Combine(quote.Path, "signWoitschetzki.png"), true);
//Create PDF twice
if (await RunningPdfLaTeX(quote, 2)) return RemoveTempFiles(quote.Path);

@ -146,8 +146,6 @@ public class QuoteHandling {
}
private static bool DoesContains(Quote quote, string type) {
if (quote.LineItems is null) return false;
foreach (LineItem lineItem in quote.LineItems)
switch (type) {
case "3PP":
@ -172,7 +170,7 @@ public class QuoteHandling {
public static async Task<Quote> GenerateQuoteFromString(Quote quote, Contact recipient, string fileContent) {
quote = ReadLineItems(quote, recipient, fileContent);
if (quote.LineItems.Count == 0) return quote;
if (recipient.Account is not null) quote.Path = HostingService.GetPath(quote, recipient) ?? "Path not found!";
if (recipient.Account is not null) quote.Path = HostingService.GetQuotePath(quote, recipient) ?? "Path not found!";
FileService.WriteQuoteToTsv(fileContent, quote);
quote = await GetCustomDescriptionsForLineItems(quote);
return quote;

@ -15,55 +15,72 @@ public static class TexService {
}
private static StringBuilder? CreateBriefkopf(Contact recipient, bool tex = false) {
if (recipient.Account.AccountName is null) return null;
if (recipient.Account?.AccountName is null) return null;
StringBuilder briefkopf = new();
if (recipient.Gender == (byte)Gender.Male) briefkopf.AppendLine($"Herr {recipient.FirstName} {recipient.LastName}");
else briefkopf.AppendLine($"Frau {recipient.FirstName} {recipient.LastName}");
if (tex) briefkopf.AppendLine("\\\\");
if (tex) briefkopf.AppendLine(@"\\");
//AccountNamen mit "&" im Namen abfangen
string accountName = recipient.Account.AccountName.Replace("&", "\\&");
briefkopf.AppendLine($"{accountName}");
if (tex) briefkopf.AppendLine("\\\\");
if (tex) briefkopf.AppendLine(@"\\");
briefkopf.AppendLine($"{recipient.Account.Street}");
if (tex) briefkopf.AppendLine("\\\\");
if (tex) briefkopf.AppendLine(@"\\");
briefkopf.AppendLine($"{recipient.Account.Zip} {recipient.Account.City}");
if (tex) briefkopf.AppendLine("\\\\");
if (tex) briefkopf.AppendLine(@"\\");
return briefkopf;
}
private static async Task<StringBuilder?> CreateTexFile(Quote quote) {
if (quote.LineItems is null) return null;
const string rand = "2"; //RUSettingModel.GetSettingValue(Properties.Settings.Default.userSettingID, "texRand");
StringBuilder texFile = new("\\documentclass[a4paper,ngerman,parskip,10pt]{scrlttr2}\n" + "\\usepackage{lmodern}\n" + "\\usepackage[T1]{fontenc}\n" + "\\usepackage[utf8]{inputenc}\n" + "\\usepackage{babel}\n" + "\\usepackage[hidelinks]{hyperref}\n");
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("\\usepackage[table]{xcolor}\n" + "\\usepackage[right]{{eurosym}}\n" +
"\\usepackage[locale=DE]{{siunitx}}\n" + "\\usepackage{{scrlayer-scrpage}}\n" +
"\\usepackage{{lastpage}}\n" + "\\usepackage{{graphicx}}\n" + "\\usepackage{{multirow}}\n" +
"\\usepackage{{longtable}}\n" + "\\usepackage{{enumitem}}\n" +
"\\usepackage{{fp, xstring, spreadtab, numprint}}\n" +
@"\DeclareSIUnit{{\sieuro}}{{\mbox{{\euro}}}}");
texFile.AppendLine($"\\rohead{{{quote.QuotationNumber}}}");
texFile.AppendLine("\\cfoot{Seite \\thepage/\\pageref{LastPage}}\n" + "\\sisetup{round-integer-to-decimal,round-precision=2,round-mode=places}" + "\n\\newcommand{\\produkttitel}[1]{\\textsc{#1}}" + "\n\\renewcommand{\\arraystretch}{1.2}\n\\definecolor{AgilentBlau}{HTML}{0085d5}" + "\n\\setlist{noitemsep}\n\\begin{document}" + "\n\\begin{tabular}{p{0.4\\hsize}p{0.5\\hsize}}" + "\n\\multirow{4}{*}{\\includegraphics[width=0.9\\hsize]{agilentLogo.png}}" + "\n&\\normalsize{Agilent Technologies Deutschland GmbH}\\\\" + "\n&\\normalsize{Life Sciences \\& Chemical Analysis}\\\\" + "\n&\\normalsize{Hewlett-Packard-Str. 8}\\\\" + "\n&\\normalsize{D-76337 Waldbronn}" + "\n\\end{tabular}" + "\n\\par\n\\begin{flushright}");
texFile.AppendLine("\\cfoot{Seite \\thepage/\\pageref{LastPage}}\n" +
"\\sisetup{round-integer-to-decimal,round-precision=2,round-mode=places}" +
"\n\\newcommand{\\produkttitel}[1]{\\textsc{#1}}" +
"\n\\renewcommand{\\arraystretch}{1.2}\n\\definecolor{AgilentBlau}{HTML}{0085d5}" +
"\n\\setlist{noitemsep}\n\\begin{document}" +
"\n\\begin{tabular}{p{0.4\\hsize}p{0.5\\hsize}}" +
"\n\\multirow{4}{*}{\\includegraphics[width=0.9\\hsize]{agilentLogo.png}}" +
"\n&\\normalsize{Agilent Technologies Deutschland GmbH}\\\\" +
"\n&\\normalsize{Life Sciences \\& Chemical Analysis}\\\\" +
"\n&\\normalsize{Hewlett-Packard-Str. 8}\\\\" + "\n&\\normalsize{D-76337 Waldbronn}" +
"\n\\end{tabular}" + "\n\\par\n\\begin{flushright}");
texFile.AppendLine(quote.IsPriceInformation ? "\n\\colorbox{AgilentBlau}{\\textcolor{white}{\\textsc{\\Huge{Preisinformation}}}}\n\\end{flushright}\n\\begin{tabular}{p{0.4\\hsize}p{0.6\\hsize}}" : "\n\\colorbox{AgilentBlau}{\\textcolor{white}{\\textsc{\\Huge{Angebot}}}}\n\\end{flushright}\n\\begin{tabular}{p{0.4\\hsize}p{0.6\\hsize}}");
texFile.AppendLine("\n &\n\\multirow{4}{*}{" + "\n\\begin{tabular}{|ll|}" + "\n\\hline");
texFile.AppendLine($"\\textbf{{Angebotsnummer:}}&{quote.QuotationNumber}\\\\");
texFile.AppendLine($@"\textbf{{Angebotsnummer:}}&{quote.QuotationNumber}\\");
texFile.Append($"Angebotdatum:&\\today\\\\\nAngebotsgültigkeit:&{quote.ValidFor} Tage\\\\");
SalesRep? salesRep = GenericController.Get<SalesRep>(sR => sR.SalesRepId.Equals(quote.SalesRepId));
if (salesRep is not null) {
texFile.AppendLine($"\\textbf{{Ansprechpartner:}}&{salesRep.FirstName} {salesRep.LastName}\\\\");
texFile.AppendLine($"Telefon: &{salesRep.PhoneNumber}\\\\");
texFile.AppendLine($"Mobil:&{salesRep.MobileNumber}\\\\");
texFile.AppendLine($"E-Mail:&\\href{{mailto:{salesRep.EMail}}}{{{salesRep.EMail}}}\\\\");
texFile.AppendLine($@"\textbf{{Ansprechpartner:}}&{salesRep.FirstName} {salesRep.LastName}\\");
texFile.AppendLine($@"Telefon: &{salesRep.PhoneNumber}\\");
texFile.AppendLine($@"Mobil:&{salesRep.MobileNumber}\\");
texFile.AppendLine($@"E-Mail:&\href{{mailto:{salesRep.EMail}}}{{{salesRep.EMail}}}\\");
}
else {
Debug.WriteLine("No SalesRep in Quote!");
@ -97,19 +114,19 @@ public static class TexService {
switch (quote.ShowDiscounts) {
case false:
//mit Einzelpreisen
texFile.AppendLine("{| cp{0.71\\textwidth} cr |} \\hline");
texFile.AppendLine(@"{| cp{0.71\textwidth} cr |} \hline");
texFile.AppendLine(@"\textbf{\#} & \textbf{Produktbeschreibung} (Produktnummer) & \textbf{Menge} & \textbf{Preis}\\ \hline \endhead");
break;
case true:
//mit Einzelpreisen und Discounts
texFile.AppendLine("{| cp{0.595\\textwidth} crr |} \\hline");
texFile.AppendLine(@"{| cp{0.595\textwidth} crr |} \hline");
texFile.AppendLine(@"\textbf{\#} & \textbf{Produktbeschreibung} (Produktnummer) & \textbf{Menge} & \textbf{Discount} & \textbf{Preis}\\ \hline \endhead");
break;
}
}
else {
//ohne Einzelpreise
texFile.AppendLine("{| cp{0.83\\textwidth} c |} \\hline");
texFile.AppendLine(@"{| cp{0.83\textwidth} c |} \hline");
texFile.AppendLine(@"\textbf{\#} & \textbf{Produktbeschreibung} (Produktnummer) & \textbf{Menge}\\ \hline \endhead");
}
@ -128,18 +145,18 @@ public static class TexService {
switch (quote.ShowSinglePrices) {
case true when !quote.ShowDiscounts:
//mit Einzelpreisen
lineItemTex = lineItem.OptionNumber != "" ? $"{lineItem.Position} &\\textbf{{{customDescription.Heading}}} ({lineItem.ProductNumber}\\#{lineItem.OptionNumber})\\newline {customDescription.DescriptionText}&{lineItem.Amount}&\\SI{{{lineItem.Total}}}{{\\sieuro}}\\\\" : $"{lineItem.Position} &\\textbf{{{customDescription.Heading}}} ({lineItem.ProductNumber})\\newline {customDescription.DescriptionText}&{lineItem.Amount}&\\SI{{{lineItem.Total}}}{{\\sieuro}}\\\\";
lineItemTex = lineItem.OptionNumber != "" ? $@"{lineItem.Position} &\textbf{{{customDescription.Heading}}} ({lineItem.ProductNumber}\#{lineItem.OptionNumber})\newline {customDescription.DescriptionText}&{lineItem.Amount}&\SI{{{lineItem.Total}}}{{\sieuro}}\\" : $@"{lineItem.Position} &\textbf{{{customDescription.Heading}}} ({lineItem.ProductNumber})\newline {customDescription.DescriptionText}&{lineItem.Amount}&\SI{{{lineItem.Total}}}{{\sieuro}}\\";
break;
case true: {
if (quote.ShowDiscounts)
//mit Einzelpreisen und Discounts
lineItemTex = lineItem.OptionNumber != "" ? $"{lineItem.Position} &\\textbf{{{customDescription.Heading}}} ({lineItem.ProductNumber}\\#{lineItem.OptionNumber})\\newline {customDescription.DescriptionText}\\newline Listenpreis: \\SI{{{lineItem.ListPrice}}}{{\\sieuro}}&{lineItem.Amount}&\\SI{{{lineItem.TotalDiscount}}}{{\\%}}&\\SI{{{lineItem.Total}}}{{\\sieuro}}\\\\" : $"{lineItem.Position} &\\textbf{{{customDescription.Heading}}} ({lineItem.ProductNumber})\\newline {customDescription.DescriptionText}\\newline Listenpreis: \\SI{{{lineItem.ListPrice}}}{{\\sieuro}}&{lineItem.Amount}&\\SI{{{lineItem.TotalDiscount}}}{{\\%}}&\\SI{{{lineItem.Total}}}{{\\sieuro}}\\\\";
lineItemTex = lineItem.OptionNumber != "" ? $@"{lineItem.Position} &\textbf{{{customDescription.Heading}}} ({lineItem.ProductNumber}\#{lineItem.OptionNumber})\newline {customDescription.DescriptionText}\newline Listenpreis: \SI{{{lineItem.ListPrice}}}{{\sieuro}}&{lineItem.Amount}&\SI{{{lineItem.TotalDiscount}}}{{\%}}&\SI{{{lineItem.Total}}}{{\sieuro}}\\" : $@"{lineItem.Position} &\textbf{{{customDescription.Heading}}} ({lineItem.ProductNumber})\newline {customDescription.DescriptionText}\newline Listenpreis: \SI{{{lineItem.ListPrice}}}{{\sieuro}}&{lineItem.Amount}&\SI{{{lineItem.TotalDiscount}}}{{\%}}&\SI{{{lineItem.Total}}}{{\sieuro}}\\";
break;
}
case false:
//ohne Einzelpreise
lineItemTex = lineItem.OptionNumber != "" ? $"{lineItem.Position} &\\textbf{{{customDescription.Heading}}} ({lineItem.ProductNumber}\\#{lineItem.OptionNumber})\\newline {customDescription.DescriptionText}&{lineItem.Amount}\\\\" : $"{lineItem.Position} &\\textbf{{{customDescription.Heading}}} ({lineItem.ProductNumber})\\newline {customDescription.DescriptionText}&{lineItem.Amount}\\\\";
lineItemTex = lineItem.OptionNumber != "" ? $@"{lineItem.Position} &\textbf{{{customDescription.Heading}}} ({lineItem.ProductNumber}\#{lineItem.OptionNumber})\newline {customDescription.DescriptionText}&{lineItem.Amount}\\" : $@"{lineItem.Position} &\textbf{{{customDescription.Heading}}} ({lineItem.ProductNumber})\newline {customDescription.DescriptionText}&{lineItem.Amount}\\";
break;
}
@ -151,18 +168,18 @@ public static class TexService {
texFile.AppendLine("\\vspace{-2cm}\n" + "\\begin{flushright}\n\n" + "\\begin{tabular}{|rr|}\n" + "\\hline");
//Summe netto
texFile.AppendLine($"\\textbf{{Summe netto}} & \\SI{{{quote.TotalNet}}}{{\\sieuro}}\\\\");
texFile.AppendLine($@"\textbf{{Summe netto}} & \SI{{{quote.TotalNet}}}{{\sieuro}}\\");
//Frachtkosten
texFile.AppendLine($"\\textbf{{Versand und Bereitstellungskosten ({quote.Freight}\\%)}} & \\SI{{{quote.TotalFreightOnly}}}{{\\sieuro}}\\\\");
texFile.AppendLine($@"\textbf{{Versand und Bereitstellungskosten ({quote.Freight}\%)}} & \SI{{{quote.TotalFreightOnly}}}{{\sieuro}}\\");
//Gesamtsumme netto
texFile.AppendLine($"\\textbf{{Gesamtsumme netto}} & \\SI{{{quote.TotalFreight}}}{{\\sieuro}}\\\\");
texFile.AppendLine($@"\textbf{{Gesamtsumme netto}} & \SI{{{quote.TotalFreight}}}{{\sieuro}}\\");
//mit Mehrwertsteuer
if (quote.ShowBrutto) {
texFile.AppendLine($"\\textbf{{Umsatzsteuer ({quote.Vat}\\%)}} & \\SI{{{quote.TotalVat}}}{{\\sieuro}}\\\\");
texFile.AppendLine($"\\textbf{{Gesamtsumme brutto}} & \\SI{{{quote.TotalGross}}}{{\\sieuro}}\\\\");
texFile.AppendLine($@"\textbf{{Umsatzsteuer ({quote.Vat}\%)}} & \SI{{{quote.TotalVat}}}{{\sieuro}}\\");
texFile.AppendLine($@"\textbf{{Gesamtsumme brutto}} & \SI{{{quote.TotalGross}}}{{\sieuro}}\\");
}
texFile.Append("\\hline\n\\end{tabular}\n\n\\end{flushright}\n\nDer Betrag versteht sich zzgl. der gesetzlichen Steuern.\\\\\nDiese werden im Rechnungszeitraum auf der Rechnung gesondert ausgewiesen.\\\\\nZahlungsbedingungen: 30 Tage netto ab Rechnungsdatum.\\\\\nIncoterm (2010) für Lieferungen innerhalb Deutschlands: DDP.\n\\begin{small}\n\n");

@ -1,7 +1,27 @@
version: "3.3"
services:
web:
container_name: gremlin_docker
gremlin:
container_name: gremlin
build:
context: ..
dockerfile: /home/sascha/current_coding/Gremlin/Gremlin_BlazorServer/Dockerfile
dockerfile: Dockerfile
environment:
- ASPNETCORE_ENVIRONMENT=Development
# - ASPNETCORE_URLS=https://localhost,http://localhost
- ASPNETCORE_HTTPS_PORT=8080
labels:
traefik.enable: "true"
traefik.http.routers.gremlin.entrypoints: "websecure"
traefik.http.routers.gremlin.rule: "Host(`gremlin.woitschetzki.de`)"
traefik.http.routers.gremlin.service: "gremlin"
traefik.http.routers.gremlin.tls: "true"
traefik.http.routers.gremlin.tls.certresolver: "tls_resolver"
traefik.http.services.gremlin.loadBalancer.server.port: "8080"
networks:
- proxy
networks:
proxy:
external: true

@ -20,7 +20,7 @@
"commandName": "Gremlin_BlazorServer",
"launchBrowser": true,
"inspectUri": "{wsProtocol}://localhost:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "https://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}