InvokeAsync(
+ string code,
+ IBillable billable,
+ OutputFormat format,
+ bool asBill,
+ SiteSettings settings
+ )
+ {
+ var di = new DirectoryInfo(settings.Bills);
+ var dia = new DirectoryInfo(settings.Avatars);
+ ViewBag.BillsDir = di.FullName;
+ ViewBag.AvatarsDir = dia.FullName;
+ ViewBag.AsBill = asBill; // vrai pour une facture, sinon, c'est un devis
+ ViewBag.Acquitted = billable.GetIsAcquitted();
+
+ ViewBag.BillingCode = code;
+ var client = await dbContext.Users
+ .Include(u=>u.PostalAddress)
+ .SingleAsync(u=>u.Id == billable.ClientId);
+ ViewBag.Client = client;
+ var performer = await dbContext.Users
+ .Include(u=>u.BankInfo)
+ .Include(u=>u.PostalAddress)
+ .SingleAsync(u=>u.Id == billable.PerformerId);
+ ViewBag.Performer = performer;
+ string clientAddress = client.PostalAddress?.Address ?? null;
+ ViewBag.ClientAddress = clientAddress.SplitAddressToTeX();
+
+
+ var profile = await dbContext.Performers
+ .Include(p=>p.OrganizationAddress)
+ .SingleAsync(p=>p.PerformerId == billable.PerformerId);
+ ViewBag.PerformerProfile = profile;
+ ViewBag.ActivityLabel = (await dbContext.Activities.SingleAsync(a => a.Code == billable.ActivityCode)).Name;
+
+ var proAddr = profile.OrganizationAddress.Address;
+ ViewBag.PerformerOrganizationAddress = proAddr.SplitAddressToTeX() ;
+ ViewBag.FooterPerformerOrganizationAddress = proAddr.SplitAddressToTeX(", ");
+
+ ViewBag.PerformerAddress = performer.PostalAddress?.Address.SplitAddressToTeX() ;
+ switch (format) {
+ case OutputFormat.LaTeX :
+ return this.View("Bill_tex", billable);
+ case OutputFormat.Pdf :
+ string tex = null;
+ var oldWriter = ViewComponentContext.ViewContext.Writer;
+ using (var writer = new StringWriter())
+ {
+ this.ViewComponentContext.ViewContext.Writer = writer;
+ var resultTex = View("Bill_tex", billable);
+ await resultTex.ExecuteAsync(this.ViewComponentContext);
+ tex = writer.ToString();
+ }
+ ViewComponentContext.ViewContext.Writer = oldWriter;
+
+ var pdfGenerationViewModel = new PdfGenerationViewModel
+ {
+ Temp = siteSettings.TempDir,
+ TeXSource = tex,
+ DestDir = siteSettings.Bills,
+ BaseFileName = billable.GetFileBaseName(billing)
+ };
+ if (settings.GenerateEstimatePdf(pdfGenerationViewModel)) {
+ return this.View(new { Generated = pdfGenerationViewModel.BaseFileName+".pdf" });
+ } else {
+ return View(new { Error = pdfGenerationViewModel.GenerationErrorMessage } );
+ }
+ }
+ ViewBag.BillFileInfo = billable.GetBillInfo(billing, siteSettings);
+ ViewBag.Settings = settings;
+ return View("Default",billable);
+
+ }
+
+ }
+}
diff --git a/src/Yavsc.Api/ViewModels/Gen/PdfGenerationViewModel.cs b/src/Yavsc.Org/ViewModels/Gen/PdfGenerationViewModel.cs
similarity index 98%
rename from src/Yavsc.Api/ViewModels/Gen/PdfGenerationViewModel.cs
rename to src/Yavsc.Org/ViewModels/Gen/PdfGenerationViewModel.cs
index 841e8d5dd..fe934e3ac 100644
--- a/src/Yavsc.Api/ViewModels/Gen/PdfGenerationViewModel.cs
+++ b/src/Yavsc.Org/ViewModels/Gen/PdfGenerationViewModel.cs
@@ -5,7 +5,7 @@ namespace Yavsc.ViewModels.Gen
{
public class PdfGenerationViewModel
{
-
+
[Required]
public string TeXSource { get; set; }
[Required]
diff --git a/src/Yavsc.Org/Views/Shared/Components/Bill/Bill_pdf.cshtml b/src/Yavsc.Org/Views/Shared/Components/Bill/Bill_pdf.cshtml
new file mode 100644
index 000000000..f49fad802
--- /dev/null
+++ b/src/Yavsc.Org/Views/Shared/Components/Bill/Bill_pdf.cshtml
@@ -0,0 +1,21 @@
+@using System.Reflection
+@using System.IO
+@using Microsoft.Extensions.WebEncoders
+@using System.Diagnostics
+@using System.Text
+@using Yavsc.Helpers
+@model Yavsc.ViewModels.Gen.PdfGenerationViewModel
+
+@{
+ ViewBag.Settings.GenerateEstimatePdf(Model);
+}
+@if (Model.Generated) {
+
+ @(Model.BaseFileName).pdf was generated
+
+} else {
+
+ @Model.GenerationErrorMessage
+
Something went wrong ...
+
+}
diff --git a/src/Yavsc.Api/Views/Shared/Bill_tex.cshtml b/src/Yavsc.Org/Views/Shared/Components/Bill/Bill_tex.cshtml
similarity index 99%
rename from src/Yavsc.Api/Views/Shared/Bill_tex.cshtml
rename to src/Yavsc.Org/Views/Shared/Components/Bill/Bill_tex.cshtml
index f0a3d2ad3..353d124e0 100644
--- a/src/Yavsc.Api/Views/Shared/Bill_tex.cshtml
+++ b/src/Yavsc.Org/Views/Shared/Components/Bill/Bill_tex.cshtml
@@ -3,7 +3,7 @@
@using System.Globalization
@model IBillable
@{
- Layout = null;
+ Layout = "null";
var pro = ViewBag.PerformerProfile;
var from = ViewBag.Performer;
var to = ViewBag.Client;
diff --git a/src/Yavsc.Org/Views/Shared/Components/Bill/Default.cshtml b/src/Yavsc.Org/Views/Shared/Components/Bill/Default.cshtml
new file mode 100644
index 000000000..f2d0e0163
--- /dev/null
+++ b/src/Yavsc.Org/Views/Shared/Components/Bill/Default.cshtml
@@ -0,0 +1,33 @@
+
+@model IBillable
+
diff --git a/src/Yavsc.Org/Views/Shared/Components/Estimate/Default.cshtml b/src/Yavsc.Org/Views/Shared/Components/Estimate/Default.cshtml
new file mode 100644
index 000000000..b9a1ab26d
--- /dev/null
+++ b/src/Yavsc.Org/Views/Shared/Components/Estimate/Default.cshtml
@@ -0,0 +1,13 @@
+
+@model Estimate
+
diff --git a/src/Yavsc.Org/Views/Shared/Components/Estimate/Estimate_pdf.cshtml b/src/Yavsc.Org/Views/Shared/Components/Estimate/Estimate_pdf.cshtml
new file mode 100644
index 000000000..bef19b35a
--- /dev/null
+++ b/src/Yavsc.Org/Views/Shared/Components/Estimate/Estimate_pdf.cshtml
@@ -0,0 +1,21 @@
+@using System.Reflection
+@using System.IO
+@using Microsoft.Extensions.WebEncoders
+@using System.Diagnostics
+@using System.Text
+@using Yavsc.Helpers
+@model Yavsc.ViewModels.Gen.PdfGenerationViewModel
+
+@{
+ SiteSettings.Value.GenerateEstimatePdf(Model);
+}
+@if (Model.Generated) {
+
+ @(Model.BaseFileName).pdf was generated
+
+} else {
+
+ @Model.GenerationErrorMessage
+
Something went wrong ...
+
+}
diff --git a/src/Yavsc.Api/Views/Shared/Estimate_tex.cshtml b/src/Yavsc.Org/Views/Shared/Components/Estimate/Estimate_tex.cshtml
similarity index 72%
rename from src/Yavsc.Api/Views/Shared/Estimate_tex.cshtml
rename to src/Yavsc.Org/Views/Shared/Components/Estimate/Estimate_tex.cshtml
index bbe4326b4..4c35d4bdd 100644
--- a/src/Yavsc.Api/Views/Shared/Estimate_tex.cshtml
+++ b/src/Yavsc.Org/Views/Shared/Components/Estimate/Estimate_tex.cshtml
@@ -3,7 +3,7 @@
@using System.Globalization
@model Estimate
@{
- Layout = null;
+ Layout = "null";
var pro = Model.Query.PerformerProfile;
var from = Model.Query.PerformerProfile.Performer;
var to = Model.Query.Client;
@@ -11,6 +11,7 @@
var proaddr = Model.Query.PerformerProfile.OrganizationAddress.Address.SplitAddressToTeX();
var proaddrm = new HtmlString(Model.Query.PerformerProfile.OrganizationAddress.Address);
var isestimate = !ViewBag.AsBill;
+ var prosign = new FileInfo($"{ViewBag.BillsDir}/estimate-prosign-{Model.Id}.png");
}
\documentclass[french,11pt]{article}
@@ -24,7 +25,6 @@
\usepackage{graphicx}
\usepackage{fancyhdr}
\usepackage{fp}
-\usepackage{tikz}
\def\TVA{20} % Taux de la TVA
@@ -49,7 +49,7 @@
\global\let\TotalHT\TotalHT
\global\let\TotalTVA\TotalTVA
\global\let\TotalTTC\TotalTTC
- \cr
+ \cr
\hline
\textbf{Total} & & & \TotalHT
}
@@ -77,12 +77,12 @@
% Infos Client
\def\ClientNom{@TeXHelpers.ToTeX(to.UserName)} % Nom du client
-\def\ClientAdresse{
+\def\ClientAdresse{
% Adresse du client
@PostalAddress
@if (PostalAddress!=null) {@PostalAddress}
@if (!string.IsNullOrWhiteSpace(to.PhoneNumber)) {@TeXHelpers.ToTeX(to.PhoneNumber)\\
- }
+ }
E-mail: @TeXHelpers.ToTeX(to.Email)
}
@@ -105,7 +105,7 @@
\renewcommand{\headrulewidth}{0pt}
\cfoot{ @TeXHelpers.ToTeX(from.UserName) @if (proaddrm!=null) { - @proaddrm } \newline
- \small{ E-mail: @TeXHelpers.ToTeX(from.Email) @if (!string.IsNullOrWhiteSpace(from.PhoneNumber)) { - Téléphone fixe: @TeXHelpers.ToTeX(from.PhoneNumber) }
+ \small{ E-mail: @TeXHelpers.ToTeX(from.Email) @if (!string.IsNullOrWhiteSpace(from.PhoneNumber)) { - Téléphone fixe: @TeXHelpers.ToTeX(from.PhoneNumber) }
}
}
@@ -113,10 +113,10 @@
% Logo de la société
@if (from.Avatar != null) {
-\includegraphics[height=60pt, viewport=0 0 128 128]{@(ViewBag.AvatarsDir)/@(from.UserName).png}
+\includegraphics[height=60pt]{@(ViewBag.AvatarsDir)/@(from.UserName).png}
-} else {
-%\includegraphics[height=60pt, viewport=0 0 128 128]{logo.png}
+} else {
+%\includegraphics{logo.png}
}
% Nom et adresse de la société
@@ -170,12 +170,12 @@
\begin{center}
\begin{tabular}{|c c c c|}
@if (!string.IsNullOrWhiteSpace(bi.BankCode) && !string.IsNullOrWhiteSpace(bi.WicketCode)
- && !string.IsNullOrWhiteSpace(bi.AccountNumber) ) {
+ && !string.IsNullOrWhiteSpace(bi.AccountNumber) ) {
\hline \textbf{Code banque} & \textbf{Code guichet} & \textbf{N° de Compte} & \textbf{Clé RIB} \\
@bi.BankCode & @bi.WicketCode & @bi.AccountNumber & @bi.BankedKey \\
}
- @if (!string.IsNullOrWhiteSpace(@bi.IBAN) && !string.IsNullOrWhiteSpace(@bi.BIC)) {
+ @if (!string.IsNullOrWhiteSpace(@bi.IBAN) && !string.IsNullOrWhiteSpace(@bi.BIC)) {
\hline \textbf{IBAN N°} & \multicolumn{3}{|l|}{ @bi.IBAN } \\
\hline \textbf{Code BIC} & \multicolumn{3}{|l|}{ @bi.BIC }
@@ -188,46 +188,19 @@
}
-@{
- // Captured signatures, if any. The Estimate.Signatures collection
- // is loaded by the controller; SignaturePro/SignatureClient project
- // the row by type. We draw them as vector TikZ at the foot of the
- // devis (see TeXHelpers.SignatureToTikz), so there is no PNG to
- // produce or \includegraphics to fail on.
- var fr = CultureInfo.CreateSpecificCulture("fr-FR");
- var proSig = Model.SignaturePro;
- var cliSig = Model.SignatureClient;
+@if (!(Model.ProviderValidationDate==null)) {
+
+\begin{flushright}
+ @(new HtmlString(isestimate?"Devis validé":"Facture validée")) le @TeXHelpers.ToTeX(Model.ProviderValidationDate.ToString("dddd dd MMMM yyyy"))
+\end{flushright}
+@if (prosign.Exists) {
+
+\begin{center}
+ \hspace{263pt}
+ \includegraphics[height=60pt]{@(ViewBag.BillsDir)/estimate-prosign-@(Model.Id).png}
+\end{center}
+
}
-
-\vspace{2em}
-\noindent
-\begin{minipage}[t]{0.45\textwidth}
- \textbf{Signature du fournisseur}\\
-@if (Model.ProviderValidationDate != default(DateTime)) {
-\small Validé le @TeXHelpers.ToTeX(Model.ProviderValidationDate.ToString("dddd dd MMMM yyyy", fr))\\
+
}
-@if (proSig != null && proSig.Strokes != null && proSig.Strokes.Length > 0) {
-\begin{tikzpicture}
- \useasboundingbox (0,0) rectangle (5,2.5);
- @proSig.SignatureToTikz(5, 2.5)
-\end{tikzpicture}
-} else {
-\rule[-2.2cm]{5cm}{0.4pt}
-}
-\end{minipage}\hfill
-\begin{minipage}[t]{0.45\textwidth}
- \textbf{Signature du client}\\
-@if (Model.ClientValidationDate != default(DateTime)) {
-\small Validé le @TeXHelpers.ToTeX(Model.ClientValidationDate.ToString("dddd dd MMMM yyyy", fr))\\
-}
-@if (cliSig != null && cliSig.Strokes != null && cliSig.Strokes.Length > 0) {
-\begin{tikzpicture}
- \useasboundingbox (0,0) rectangle (5,2.5);
- @cliSig.SignatureToTikz(5, 2.5)
-\end{tikzpicture}
-} else {
-\rule[-2.2cm]{5cm}{0.4pt}
-}
-\end{minipage}
-
\end{document}
diff --git a/src/Yavsc.Org/Yavsc.Org.csproj b/src/Yavsc.Org/Yavsc.Org.csproj
index 99e0cf29c..928faf7c8 100644
--- a/src/Yavsc.Org/Yavsc.Org.csproj
+++ b/src/Yavsc.Org/Yavsc.Org.csproj
@@ -9,8 +9,8 @@
https://github.com/pazof/yavsc
1.1.0.0
1.1.0.0
- 1.1.0-estimate.1+343.Branch.feature-estimate.Sha.ba40698cc9562f0f4ad2dcad4dd20e638c05b07d
- 1.1.0-estimate.1
+ 1.1.0-feat-sign-estimate.1+306.Branch.feat-sign-estimate.Sha.e9a33695b38154859729b61d1280e596f1597acf
+ 1.1.0-feat-sign-estimate.1
@@ -47,4 +47,4 @@
-
\ No newline at end of file
+
diff --git a/src/Yavsc.Server/Helpers/FileSystemHelpers.cs b/src/Yavsc.Server/Helpers/FileSystemHelpers.cs
index 77e691ea5..bc7b9c81d 100644
--- a/src/Yavsc.Server/Helpers/FileSystemHelpers.cs
+++ b/src/Yavsc.Server/Helpers/FileSystemHelpers.cs
@@ -34,7 +34,7 @@ namespace Yavsc.Server.Helpers
{
var item = new FileReceivedInfo(
settings.Bills,
- AbstractFileSystemHelpers.SignFileNameFormat(signType, billingCode, estimateId));
+ AbstractFileSystemHelpers.SignFileNameFormat("pro", billingCode, estimateId));
var fi = new FileInfo(item.FullName);
if (fi.Exists) item.Overridden = true;
diff --git a/src/Yavsc.Server/Models/Billing/Estimate.cs b/src/Yavsc.Server/Models/Billing/Estimate.cs
index 8a26faab9..74680e7b7 100644
--- a/src/Yavsc.Server/Models/Billing/Estimate.cs
+++ b/src/Yavsc.Server/Models/Billing/Estimate.cs
@@ -8,7 +8,6 @@ namespace Yavsc.Models.Billing
{
using Models.Workflow;
using Newtonsoft.Json;
- using System.Linq;
public partial class Estimate : IEstimate
{
@@ -79,39 +78,14 @@ namespace Yavsc.Models.Billing
public DateTime ClientValidationDate { get; set; }
///
- /// All signatures captured against this estimate, keyed by
- /// . The persister upserts by
- /// (EstimateId, Type), so there is at most one row per type.
- /// This collection is the persisted shape and stays
- /// [JsonIgnore]: the wire payload exposes signatures
- /// only through the dedicated and
- /// projections, since an
- /// estimate has exactly these two signature slots and never
- /// more. See .
+ /// All signatures captured against this estimate, in
+ /// capture order. Multiple versions per (Type, SignerId)
+ /// are allowed; the controller reads the most recent
+ /// when asked. See .
///
[InverseProperty(nameof(Signature.Estimate))]
- [JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
public virtual ICollection Signatures { get; set; }
= new List();
- ///
- /// The provider's signature on this estimate, or null when the
- /// provider has not signed. Projected from
- /// ; not mapped (the table is
- /// ).
- ///
- [NotMapped]
- public Signature? SignaturePro
- => Signatures?.FirstOrDefault(s => s.Type == SignatureType.Pro);
-
- ///
- /// The client's signature on this estimate, or null when the
- /// client has not signed. Projected from
- /// ; not mapped.
- ///
- [NotMapped]
- public Signature? SignatureClient
- => Signatures?.FirstOrDefault(s => s.Type == SignatureType.Client);
-
}
}
diff --git a/src/Yavsc.Server/Models/Billing/Signature.cs b/src/Yavsc.Server/Models/Billing/Signature.cs
index 7e568dbd1..1aac0cd0e 100644
--- a/src/Yavsc.Server/Models/Billing/Signature.cs
+++ b/src/Yavsc.Server/Models/Billing/Signature.cs
@@ -31,7 +31,7 @@ public class Signature
public long EstimateId { get; set; }
- [ForeignKey(nameof(EstimateId)), JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
+ [ForeignKey(nameof(EstimateId)), JsonIgnore]
public virtual Estimate Estimate { get; set; }
///
@@ -48,7 +48,7 @@ public class Signature
[Required]
public string SignerId { get; set; }
- [ForeignKey(nameof(SignerId)), JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
+ [ForeignKey(nameof(SignerId)), JsonIgnore]
public virtual ApplicationUser Signer { get; set; }
public SignatureType Type { get; set; }
diff --git a/src/Yavsc.Abstract/Billing/SignatureType.cs b/src/Yavsc.Server/Models/Billing/SignatureType.cs
similarity index 99%
rename from src/Yavsc.Abstract/Billing/SignatureType.cs
rename to src/Yavsc.Server/Models/Billing/SignatureType.cs
index 5a27f5cdd..7c27924fd 100644
--- a/src/Yavsc.Abstract/Billing/SignatureType.cs
+++ b/src/Yavsc.Server/Models/Billing/SignatureType.cs
@@ -12,4 +12,4 @@ public enum SignatureType
{
Pro = 0,
Client = 1,
-}
\ No newline at end of file
+}
diff --git a/src/Yavsc.Server/Yavsc.Server.csproj b/src/Yavsc.Server/Yavsc.Server.csproj
index b291847c0..bb2022fc6 100644
--- a/src/Yavsc.Server/Yavsc.Server.csproj
+++ b/src/Yavsc.Server/Yavsc.Server.csproj
@@ -9,8 +9,8 @@
true
1.1.0.0
1.1.0.0
- 1.1.0-estimate.1+343.Branch.feature-estimate.Sha.ba40698cc9562f0f4ad2dcad4dd20e638c05b07d
- 1.1.0-estimate.1
+ 1.1.0-feat-sign-estimate.1+306.Branch.feat-sign-estimate.Sha.e9a33695b38154859729b61d1280e596f1597acf
+ 1.1.0-feat-sign-estimate.1
diff --git a/src/Yavsc.Tests.Shared/Yavsc.Tests.Shared.csproj b/src/Yavsc.Tests.Shared/Yavsc.Tests.Shared.csproj
index 830377ca2..dd93a8b34 100644
--- a/src/Yavsc.Tests.Shared/Yavsc.Tests.Shared.csproj
+++ b/src/Yavsc.Tests.Shared/Yavsc.Tests.Shared.csproj
@@ -14,8 +14,8 @@
-->
1.1.0.0
1.1.0.0
- 1.1.0-estimate.1+343.Branch.feature-estimate.Sha.ba40698cc9562f0f4ad2dcad4dd20e638c05b07d
- 1.1.0-estimate.1
+ 1.1.0-feat-sign-estimate.1+306.Branch.feat-sign-estimate.Sha.e9a33695b38154859729b61d1280e596f1597acf
+ 1.1.0-feat-sign-estimate.1
diff --git a/src/cli/cli.csproj b/src/cli/cli.csproj
index 39ef7660f..382dff670 100644
--- a/src/cli/cli.csproj
+++ b/src/cli/cli.csproj
@@ -7,8 +7,8 @@
true
1.1.0.0
1.1.0.0
- 1.1.0-estimate.1+343.Branch.feature-estimate.Sha.ba40698cc9562f0f4ad2dcad4dd20e638c05b07d
- 1.1.0-estimate.1
+ 1.1.0-feat-sign-estimate.1+306.Branch.feat-sign-estimate.Sha.e9a33695b38154859729b61d1280e596f1597acf
+ 1.1.0-feat-sign-estimate.1