diff --git a/Yavsc/ApiControllers/PdfEstimateController.cs b/Yavsc/ApiControllers/PdfEstimateController.cs new file mode 100644 index 00000000..08428c38 --- /dev/null +++ b/Yavsc/ApiControllers/PdfEstimateController.cs @@ -0,0 +1,37 @@ +using System; +using System.IO; +using System.Security.Claims; +using Microsoft.AspNet.Authorization; +using Microsoft.AspNet.Mvc; + +namespace Yavsc.ApiControllers +{ + [Route("api/pdfestimate"), Authorize] + public class PdfEstimateController : Controller + { + [HttpGet("{id}", Name = "Get")] + public IActionResult Get(long id) + { + var filename = $"estimate-{id}.pdf"; + + var cd = new System.Net.Mime.ContentDisposition + { + // for example foo.bak + FileName = filename, + + // always prompt the user for downloading, set to true if you want + // the browser to try to show the file inline + Inline = false, + }; + + FileInfo fi = new FileInfo(Path.Combine(Startup.UserBillsDirName,filename)); + + FileStreamResult result = null; + var s = fi.OpenRead(); + + result = File(s,"application/x-pdf",filename); + + return result; + } + } +} \ No newline at end of file diff --git a/Yavsc/Bills/a94433b4-f11f-4a4b-8066-b32c1ab1103d/estimate-3.pdf b/Yavsc/Bills/a94433b4-f11f-4a4b-8066-b32c1ab1103d/estimate-3.pdf new file mode 100644 index 00000000..ba625e66 Binary files /dev/null and b/Yavsc/Bills/a94433b4-f11f-4a4b-8066-b32c1ab1103d/estimate-3.pdf differ diff --git a/Yavsc/Bills/a94433b4-f11f-4a4b-8066-b32c1ab1103d/tmpestimtex-3.pdf b/Yavsc/Bills/a94433b4-f11f-4a4b-8066-b32c1ab1103d/tmpestimtex-3.pdf new file mode 100644 index 00000000..590aa15d Binary files /dev/null and b/Yavsc/Bills/a94433b4-f11f-4a4b-8066-b32c1ab1103d/tmpestimtex-3.pdf differ diff --git a/Yavsc/Bills/estimate-3.pdf b/Yavsc/Bills/estimate-3.pdf new file mode 100644 index 00000000..7f81eafc Binary files /dev/null and b/Yavsc/Bills/estimate-3.pdf differ diff --git a/Yavsc/Controllers/FrontOfficeController.cs b/Yavsc/Controllers/FrontOfficeController.cs index a7b8fb8c..8eed5407 100644 --- a/Yavsc/Controllers/FrontOfficeController.cs +++ b/Yavsc/Controllers/FrontOfficeController.cs @@ -8,10 +8,20 @@ using Microsoft.Extensions.Logging; using Yavsc.Models.Booking; using Yavsc.Helpers; using System; +using System.IO; +using System.Diagnostics; +using System.Text; +using Microsoft.AspNet.Mvc.ViewFeatures; +using Microsoft.AspNet.Razor; +using Microsoft.AspNet.Mvc.ViewEngines; +using Microsoft.AspNet.Mvc.Rendering; +using Microsoft.Extensions.OptionsModel; +using System.Threading.Tasks; +using System.Security.Claims; namespace Yavsc.Controllers { - [ServiceFilter(typeof(LanguageActionFilter)), + [ServiceFilter(typeof(LanguageActionFilter)), Route("do")] public class FrontOfficeController : Controller { @@ -35,44 +45,45 @@ namespace Yavsc.Controllers return View(latestPosts); } - [Route("Book/{id?}"),HttpGet] - + [Route("Book/{id?}"), HttpGet] public ActionResult Book(string id) { - if (id == null) { + if (id == null) + { throw new NotImplementedException("No Activity code"); } - + ViewBag.Activities = _context.ActivityItems(id); - ViewBag.Activity = _context.Activities.FirstOrDefault( - a => a.Code == id ); + ViewBag.Activity = _context.Activities.FirstOrDefault( + a => a.Code == id); return View( - _context.Performers.Include(p=>p.Performer).Where + _context.Performers.Include(p => p.Performer).Where (p => p.ActivityCode == id && p.Active).OrderBy( - x=>x.MinDailyCost + x => x.MinDailyCost ) ); } - [Route("Book/{id}"),HttpPost] - + [Route("Book/{id}"), HttpPost] public ActionResult Book(BookQuery bookQuery) { - if (ModelState.IsValid) { + if (ModelState.IsValid) + { var pro = _context.Performers.Include( pr => pr.Performer ).FirstOrDefault( - x=>x.PerformerId == bookQuery.PerformerId + x => x.PerformerId == bookQuery.PerformerId ); - if (pro==null) + if (pro == null) return HttpNotFound(); // Let's create a command - if (bookQuery.Id==0) + if (bookQuery.Id == 0) { _context.BookQueries.Add(bookQuery); } - else { + else + { _context.BookQueries.Update(bookQuery); } _context.SaveChanges(); @@ -81,36 +92,146 @@ namespace Yavsc.Controllers return View("Index"); } ViewBag.Activities = _context.ActivityItems(null); - return View( _context.Performers.Include(p=>p.Performer).Where + return View(_context.Performers.Include(p => p.Performer).Where (p => p.Active).OrderBy( - x=>x.MinDailyCost + x => x.MinDailyCost )); } [Produces("text/x-tex"), Authorize, Route("estimate-{id}.tex")] public ViewResult EstimateTex(long id) { - var estimate = _context.Estimates.Include(x=>x.Query) - .Include(x=>x.Query.Client) - .Include(x=>x.Query.PerformerProfile) - .Include(x=>x.Query.PerformerProfile.OrganizationAddress) - .Include(x=>x.Query.PerformerProfile.Performer) - .Include(e=>e.Bill).FirstOrDefault(x=>x.Id==id); + var estimate = _context.Estimates.Include(x => x.Query) + .Include(x => x.Query.Client) + .Include(x => x.Query.PerformerProfile) + .Include(x => x.Query.PerformerProfile.OrganizationAddress) + .Include(x => x.Query.PerformerProfile.Performer) + .Include(e => e.Bill).FirstOrDefault(x => x.Id == id); Response.ContentType = "text/x-tex"; return View("Estimate.tex", estimate); } - - - [Produces("application/x-pdf"), Authorize, Route("estimate-{id}.pdf")] - public ViewResult EstimatePdf(long id) + + class TeOtions : IOptions { - var estimate = _context.Estimates.Include(x=>x.Query) - .Include(x=>x.Query.Client) - .Include(x=>x.Query.PerformerProfile) - .Include(x=>x.Query.PerformerProfile.OrganizationAddress) - .Include(x=>x.Query.PerformerProfile.Performer) - .Include(e=>e.Bill).FirstOrDefault(x=>x.Id==id); - return View("Estimate.pdf", estimate); + public MvcViewOptions Value + { + get + { + return new MvcViewOptions(); + } + } } + + [Authorize,Route("Estimate-{id}.pdf")] + public async Task EstimatePdf(long id) + { + ViewBag.TempDir = Startup.SiteSetup.TempDir; + ViewBag.BillsDir = Startup.UserBillsDirName; + + var estimate = _context.Estimates.Include(x => x.Query) + .Include(x => x.Query.Client) + .Include(x => x.Query.PerformerProfile) + .Include(x => x.Query.PerformerProfile.OrganizationAddress) + .Include(x => x.Query.PerformerProfile.Performer) + .Include(e => e.Bill).FirstOrDefault(x => x.Id == id); + if (estimate==null) + throw new Exception("No data"); + + return View("Estimate.pdf",estimate); + /* + await result.ExecuteResultAsync(ActionContext); + var cd = new System.Net.Mime.ContentDisposition + { + // for example foo.bak + FileName = $"estimate-{id}.pdf", + + // always prompt the user for downloading, set to true if you want + // the browser to try to show the file inline + Inline = false, + }; + Response.Headers.Add("Content-Disposition", cd.ToString()); + return File((Byte[])ViewData["Pdf"], "application/x-pdf"); */ + } + /* + + [Produces("application/x-pdf"), Authorize, Route("testimate-{id}.pdf")] + public async Task BadEstimatePdf(long id) + { + + var tempDir = Startup.SiteSetup.TempDir; + + string name = $"tmpestimtex-{id}"; + string fullname = new FileInfo( + System.IO.Path.Combine(tempDir, name)).FullName; + var writer = new System.IO.StringWriter(); + try + { + using (StringWriter sw = new StringWriter()) + { + Microsoft.AspNet.Mvc.ViewEngines.CompositeViewEngine ve = new CompositeViewEngine( + new TeOtions {} + ); + + ViewEngineResult viewResult = ve.FindPartialView(ActionContext, $"estimate-{id}.tex"); + ViewContext viewContext = new ViewContext(); // ActionContext, viewResult.View, ViewData, TempData, sw); + await viewResult.View.RenderAsync(viewContext); + } + } catch (Exception ex) + { + } + + + + + FileInfo fo = new FileInfo(fullname + ".pdf"); + if (!fi.Exists) + { + throw new Exception("Source write failed"); + } + using (Process p = new Process()) + { + p.StartInfo.WorkingDirectory = tempDir; + p.StartInfo = new ProcessStartInfo(); + p.StartInfo.UseShellExecute = false; + p.StartInfo.FileName = "/usr/bin/texi2pdf"; + p.StartInfo.Arguments = $"--batch --build-dir=."; + + p.Start(); + + using (p.StandardInput) + { + + } + p.WaitForExit(); + if (p.ExitCode != 0) + { + throw new Exception("Pdf generation failed with exit code:" + p.ExitCode); + } + } + byte[] pdf = null; + if (fo.Exists) + { + using (StreamReader sr = new StreamReader(fo.FullName)) + { + pdf = System.IO.File.ReadAllBytes(fo.FullName); + } + fo.Delete(); + } + fi.Delete(); + + + var cd = new System.Net.Mime.ContentDisposition + { + // for example foo.bak + FileName = $"estimate-{id}.pdf", + + // always prompt the user for downloading, set to true if you want + // the browser to try to show the file inline + Inline = false, + }; + Response.Headers.Add("Content-Disposition", cd.ToString()); + return File(pdf, "application/x-pdf"); + } */ + } } \ No newline at end of file diff --git a/Yavsc/Settings/SiteSettings.cs b/Yavsc/Settings/SiteSettings.cs index 03cc63ee..7801060f 100644 --- a/Yavsc/Settings/SiteSettings.cs +++ b/Yavsc/Settings/SiteSettings.cs @@ -16,15 +16,32 @@ namespace Yavsc /// /// public string Authority { get; set; } + /// + /// Owner's email + /// + /// public EmailEntry Owner { get; set; } + /// + /// Administrator's email + /// + /// public EmailEntry Admin { get; set; } + /// + /// User's files directory + /// + /// public ThirdPartyFiles UserFiles { get; set; } public string BusinessName { get; set; } public string Street { get; set; } public string PostalCode { get; set; } public string CountryCode { get; set; } - + /// + /// Specifies the directory where should be + /// generated pdf files using pandoc + /// + /// The temporary directory to use + public string TempDir { get; set; } = "Temp"; } } diff --git a/Yavsc/Startup/Startup.FileServer.cs b/Yavsc/Startup/Startup.FileServer.cs index 2f66ed44..d9012fb0 100644 --- a/Yavsc/Startup/Startup.FileServer.cs +++ b/Yavsc/Startup/Startup.FileServer.cs @@ -12,6 +12,7 @@ namespace Yavsc { public static string UserFilesDirName { get; private set; } public static FileServerOptions UserFilesOptions { get; private set; } + public void ConfigureFileServerApp(IApplicationBuilder app, SiteSettings siteSettings, IHostingEnvironment env) { diff --git a/Yavsc/Startup/Startup.cs b/Yavsc/Startup/Startup.cs index f409d99c..bcd7ffe0 100755 --- a/Yavsc/Startup/Startup.cs +++ b/Yavsc/Startup/Startup.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; +using System.IO; using System.Reflection; using System.Threading.Tasks; using System.Web.Optimization; @@ -32,8 +33,11 @@ namespace Yavsc public partial class Startup { public static string ConnectionString { get; private set; } + public static string UserBillsDirName { private set; get; } public static string Authority { get; private set; } public static string Audience { get; private set; } + public static SiteSettings SiteSetup { get; private set; } + private static ILogger logger; public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv) { @@ -225,7 +229,11 @@ namespace Yavsc RoleManager roleManager, ILoggerFactory loggerFactory) { + SiteSetup = siteSettings.Value; + var tempdi = new DirectoryInfo(SiteSetup.TempDir); + if (!tempdi.Exists) tempdi.Create(); Startup.UserFilesDirName = siteSettings.Value.UserFiles.DirName; + Startup.UserBillsDirName = siteSettings.Value.UserFiles.Bills; loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); logger = loggerFactory.CreateLogger(); diff --git a/Yavsc/Temp/estimate-8.tex b/Yavsc/Temp/estimate-8.tex new file mode 100644 index 00000000..82c06f27 --- /dev/null +++ b/Yavsc/Temp/estimate-8.tex @@ -0,0 +1,146 @@ +\documentclass[french,11pt]{article} +\usepackage{babel} +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} +\usepackage[a4paper]{geometry} +\usepackage{units} +\usepackage{bera} +\usepackage{graphicx} +\usepackage{fancyhdr} +\usepackage{fp} + +\def\TVA{20} % Taux de la TVA + +\def\TotalHT{0} +\def\TotalTVA{0} + +\newcommand{\AjouterService}[3]{% Arguments : Désignation, quantité, prix + \FPround{\prix}{#3}{2} + \FPeval{\montant}{#2 * #3} + \FPround{\montant}{\montant}{2} + \FPadd{\TotalHT}{\TotalHT}{\montant} + + \eaddto\ListeProduits{#1 & \prix & #2 & \montant \cr} +} + + +\newcommand{\AfficheResultat}{% + \ListeProduits + + \FPeval{\TotalTVA}{\TotalHT * \TVA / 100} + \FPadd{\TotalTTC}{\TotalHT}{\TotalTVA} + \FPround{\TotalHT}{\TotalHT}{2} + \FPround{\TotalTVA}{\TotalTVA}{2} + \FPround{\TotalTTC}{\TotalTTC}{2} + \global\let\TotalHT\TotalHT + \global\let\TotalTVA\TotalTVA + \global\let\TotalTTC\TotalTTC + + + \cr + \hline + \textbf{Total} & & & \TotalHT +} + +\newcommand*\eaddto[2]{% version développée de \addto + \edef\tmp{#2}% + \expandafter\addto + \expandafter#1% + \expandafter{\tmp}% +} + +\newcommand{\ListeProduits}{} + +%%%%%%%%%%%%%%%%%%%%% A MODIFIER DANS LA FACTURE %%%%%%%%%%%%%%%%%%%%% + +\def\FactureNum {8} % Numéro de facture +\def\FactureAcquittee {non} % Facture acquittée : oui/non +\def\FactureLieu {2 Boulevard Aristide Briand, 92150 Suresnes, France} % Lieu de l'édition de la facture +\def\FactureObjet {Facture : } % Objet du document +% Description de la facture +\def\FactureDescr { + # **Hello Estimate!** coup blah +} + +% Infos Client +\def\ClientNom{Paul} % Nom du client + +\def\ClientAdresse{ +% Adresse du client + E-mail: redienhcs.luap@gmail.com +} + +% Liste des produits facturés : Désignation, prix + + +\AjouterService {une première} {3} {121,6000} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +\geometry{verbose,tmargin=4em,bmargin=8em,lmargin=6em,rmargin=6em} +\setlength{\parindent}{0pt} +\setlength{\parskip}{1ex plus 0.5ex minus 0.2ex} + +\thispagestyle{fancy} +\pagestyle{fancy} +\setlength{\parindent}{0pt} + +\renewcommand{\headrulewidth}{0pt} +\cfoot{ Paul - 2 Boulevard Aristide Briand, 92150 Suresnes, France \newline + \small{ E-mail: redienhcs.luap@gmail.com + } +} + +\begin{document} + +% Logo de la société + +%\includegraphics{logo.png} +% Nom et adresse de la société + Paul \\ + 2 Boulevard Aristide Briand, 92150 Suresnes, France + +Facture n°\FactureNum + + +{\addtolength{\leftskip}{10.5cm} %in ERT + \textbf{\ClientNom} \\ + \ClientAdresse \\ + +} %in ERT + + +\hspace*{10.5cm} +\FactureLieu, le \today + +~\\~\\ + +\textbf{Objet : \FactureObjet \\} + +\textnormal{\FactureDescr} + +~\\ + +\begin{center} + \begin{tabular}{lrrr} + \textbf{Désignation ~~~~~~} & \textbf{Prix unitaire} & \textbf{Quantité} & \textbf{Montant (EUR)} \\ + \hline + \AfficheResultat{} + \end{tabular} +\end{center} + +\begin{flushright} +\textit{Auto entreprise en franchise de TVA}\\ + +\end{flushright} +~\\ + +\ifthenelse{\equal{\FactureAcquittee}{oui}}{ + Facture acquittée. +}{ + +} +\end{document} diff --git a/Yavsc/Views/Estimate/Details.cshtml b/Yavsc/Views/Estimate/Details.cshtml index ae367964..87afc47b 100644 --- a/Yavsc/Views/Estimate/Details.cshtml +++ b/Yavsc/Views/Estimate/Details.cshtml @@ -40,5 +40,5 @@ @{ var filenametex = $"estimate-{Model.Id}.tex" ; var filenamepdf = $"estimate-{Model.Id}.pdf" ;} Export au format LaTeX - Export au format LaTeX + Export au format Pdf

diff --git a/Yavsc/Views/FrontOffice/Estimate.pdf.cshtml b/Yavsc/Views/FrontOffice/Estimate.pdf.cshtml index a8bb2b06..aefd3826 100644 --- a/Yavsc/Views/FrontOffice/Estimate.pdf.cshtml +++ b/Yavsc/Views/FrontOffice/Estimate.pdf.cshtml @@ -1,26 +1,27 @@ - -@using System.Reflection -@using System.IO -@using Microsoft.Extensions.WebEncoders -@using System.Diagnostics -@using System.Text -@using Yavsc.Formatters - +@using System.Reflection; +@using System.IO; +@using Microsoft.Extensions.WebEncoders; +@using System.Diagnostics; +@using System.Text; +@using Yavsc.Formatters; @model Estimate @{ - Layout = null; - ViewBag.Pdf = ""; - ViewBag.TeX = ""; - var writer = new System.IO.StringWriter(); - var content = await Html.PartialAsync("Estimate.tex", Model ); + if (ViewBag.TempDir==null) { throw new InvalidOperationException(); } + + ViewBag.Pdf = ""; + ViewBag.TeX = ""; + var writer = new System.IO.StringWriter(); + var content = await Html.PartialAsync("Estimate.tex", Model ); content.WriteTo(writer, new TexEncoder()); var contentStr = writer.ToString(); - string name = $"tmpestimtex-{Model.Id}"; - string fullname = new FileInfo( + string name = $"estimate-{Model.Id}"; + string fullname = new FileInfo( System.IO.Path.Combine(ViewBag.TempDir,name)).FullName; + string ofullname = new FileInfo( + System.IO.Path.Combine(ViewBag.BillsDir,name)).FullName; FileInfo fi = new FileInfo(fullname + ".tex"); - FileInfo fo = new FileInfo(fullname + ".pdf"); + FileInfo fo = new FileInfo(ofullname + ".pdf"); using (StreamWriter sw = new StreamWriter (fi.FullName)) { sw.Write (contentStr); @@ -41,15 +42,10 @@ throw new Exception ("Pdf generation failed with exit code:" + p.ExitCode); } } - if (fo.Exists) { - UTF8Encoding utf8 = new UTF8Encoding(); - - using (StreamReader sr = new StreamReader (fo.FullName)) { - byte[] buffer = File.ReadAllBytes (fo.FullName); - ViewBag.Pdf = utf8.GetString(buffer,0,buffer.Length); - } - fo.Delete(); - } + ViewBag.Success = fo.Exists; fi.Delete(); + var uri = $"~/api/pdfestimate/{Model.Id}"; + } -@ViewBag.Pdf + +@uri \ No newline at end of file diff --git a/Yavsc/estimate-3.t2d/pdf/bak/estimate-3.aux b/Yavsc/estimate-3.t2d/pdf/bak/estimate-3.aux new file mode 100644 index 00000000..2398624f --- /dev/null +++ b/Yavsc/estimate-3.t2d/pdf/bak/estimate-3.aux @@ -0,0 +1,9 @@ +\relax +\catcode `:\active +\catcode `;\active +\catcode `!\active +\catcode `?\active +\select@language{french} +\@writefile{toc}{\select@language{french}} +\@writefile{lof}{\select@language{french}} +\@writefile{lot}{\select@language{french}} diff --git a/Yavsc/tmpestimtex-3.t2d/pdf/bak/tmpestimtex-3.aux b/Yavsc/tmpestimtex-3.t2d/pdf/bak/tmpestimtex-3.aux new file mode 100644 index 00000000..2398624f --- /dev/null +++ b/Yavsc/tmpestimtex-3.t2d/pdf/bak/tmpestimtex-3.aux @@ -0,0 +1,9 @@ +\relax +\catcode `:\active +\catcode `;\active +\catcode `!\active +\catcode `?\active +\select@language{french} +\@writefile{toc}{\select@language{french}} +\@writefile{lof}{\select@language{french}} +\@writefile{lot}{\select@language{french}}