Fix lualatex stdin PDF gen + unit test for signed estimate PDF
GenerateEstimatePdf passed /dev/stdin as the input filename so lualatex treats stdin as a regular input file instead of the terminal — without it, lualatex emergency-stops after the first line of a multi-line document (the real root cause of the production "Emergency stop", not bera/luaotfload which were separate host-package gaps already fixed). EstimatePdf endpoint calls GenerateEstimatePdf directly and streams the returned FileInfo, guarding on fo.Exists. QueryAcceptanceRequest is extracted into its own file under ViewModels/FrontOffice. Add EstimatePdfGenerationTests: unit tests for SignatureToTikz (vector draws of both signatures) and GenerateEstimatePdf on a devis signed by both parties — asserts the PDF exists at the expected DestDir path, is non-empty, and that only the PDF persists (aux/log cleaned). Skips cleanly when lualatex is absent. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
parent
9c1f552bca
commit
35d784fdf1
4 changed files with 242 additions and 41 deletions
|
|
@ -140,7 +140,7 @@ namespace Yavsc.ApiControllers
|
|||
// we stream the generated PDF bytes — but driving the
|
||||
// generation through the view keeps the template as the
|
||||
// output producer, per the original design.
|
||||
if (model.GenerateEstimatePdf() is FileInfo fo)
|
||||
if (model.GenerateEstimatePdf() is FileInfo fo && fo.Exists)
|
||||
{
|
||||
return File(fo.OpenRead(), "application/pdf");
|
||||
}
|
||||
|
|
@ -370,42 +370,3 @@ namespace Yavsc.ApiControllers
|
|||
|
||||
internal enum ActorRole { None, Provider, Client, Admin }
|
||||
}
|
||||
|
||||
namespace Yavsc.ViewModels.FrontOffice
|
||||
{
|
||||
/// <summary>
|
||||
/// Body of <c>POST /api/v1/front/query/accept</c> and
|
||||
/// <c>.../reject</c>. The <see cref="Strokes"/> field is optional:
|
||||
/// when present (non-empty) on accept, it is the PostIt wire-format
|
||||
/// signature captured with the acceptance. All fields are optional
|
||||
/// so a caller may post <c>{}</c> to accept/reject without a
|
||||
/// signature.
|
||||
/// </summary>
|
||||
public class QueryAcceptanceRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Wire-format strokes. See
|
||||
/// <c>PostIt.Models.SignaturePadData</c>. Null or empty means
|
||||
/// no signature.
|
||||
/// </summary>
|
||||
public int[]? Strokes { get; set; }
|
||||
|
||||
public int CoordinateMax { get; set; } = 10_000;
|
||||
|
||||
public DateTime? CapturedAtUtc { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Which signature is being submitted:
|
||||
/// <see cref="SignatureType.Pro"/> (the provider) or
|
||||
/// <see cref="SignatureType.Client"/>. When <see cref="Strokes"/>
|
||||
/// is present this declares the side the caller is signing as;
|
||||
/// the server honors it only if the caller is that party
|
||||
/// (<c>query.PerformerId</c> for Pro, <c>query.ClientId</c>
|
||||
/// for Client). This disambiguates the case where one user is
|
||||
/// both parties, and makes "write only for its author"
|
||||
/// explicit. When null, the server falls back to the role
|
||||
/// inferred from the caller's identity.
|
||||
/// </summary>
|
||||
public SignatureType? SignatureType { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue