From 66c3febd7ae45bf5e99f270e39605842fb45835b Mon Sep 17 00:00:00 2001 From: Scott Pouliot Date: Wed, 10 Jun 2026 16:39:11 -0400 Subject: [PATCH] Move invoice PAID stamp inline to header; add email to company block - Remove watermark overlay layer; PAID badge now sits centered between the header row and the accent rule so it never obscures line items - Add PrimaryContactEmail to company info block in header - Remove ComposePaidStamp helper (no longer needed) Co-Authored-By: Claude Sonnet 4.6 --- .../Services/PdfService.cs | 40 ++++++------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/src/PowderCoating.Application/Services/PdfService.cs b/src/PowderCoating.Application/Services/PdfService.cs index 074bfbb..d91854f 100644 --- a/src/PowderCoating.Application/Services/PdfService.cs +++ b/src/PowderCoating.Application/Services/PdfService.cs @@ -98,12 +98,7 @@ public class PdfService : IPdfService page.DefaultTextStyle(x => x.FontSize(10).FontFamily("Arial")); page.Header().Element(c => ComposeInvoiceHeader(c, companyLogo, companyInfo, accentColor, invoiceDto)); - page.Content().Layers(layers => - { - layers.PrimaryLayer().Element(c => ComposeInvoiceContent(c, invoiceDto, accentColor, template)); - if (invoiceDto.Status == InvoiceStatus.Paid) - layers.Layer().Element(c => ComposePaidStamp(c)); - }); + page.Content().Element(c => ComposeInvoiceContent(c, invoiceDto, accentColor, template)); page.Footer().AlignCenter().Text(text => { text.CurrentPageNumber(); @@ -148,6 +143,8 @@ public class PdfService : IPdfService column.Item().Text(cityLine).FontSize(9).FontColor(Colors.Grey.Darken1); if (!string.IsNullOrWhiteSpace(companyInfo.Phone)) column.Item().Text(FormatPhoneNumber(companyInfo.Phone)).FontSize(9).FontColor(Colors.Grey.Darken1); + if (!string.IsNullOrWhiteSpace(companyInfo.PrimaryContactEmail)) + column.Item().Text(companyInfo.PrimaryContactEmail).FontSize(9).FontColor(Colors.Grey.Darken1); }); row.RelativeItem().AlignRight().Column(column => @@ -161,31 +158,20 @@ public class PdfService : IPdfService }); }); + if (invoice.Status == InvoiceStatus.Paid) + { + col.Item().PaddingVertical(6).AlignCenter().Column(badge => + { + badge.Item().AlignCenter().Border(2).BorderColor(Colors.Green.Darken1) + .PaddingVertical(4).PaddingHorizontal(24) + .Text("PAID").FontSize(18).Bold().FontColor(Colors.Green.Darken1).LetterSpacing(0.15f); + }); + } + col.Item().PaddingVertical(4).LineHorizontal(1).LineColor(accentColor); }); } - /// - /// Renders a semi-transparent angled PAID stamp centred over the invoice content layer. - /// Uses QuestPDF layout primitives (AlignCenter, AlignMiddle, Rotate, Opacity) so no - /// external Skia/SkiaSharp dependency is needed. - /// - private static void ComposePaidStamp(IContainer container) - { - container - .AlignCenter() - .AlignMiddle() - .Rotate(-45f) - .Border(2) - .BorderColor(Colors.Green.Lighten2) - .PaddingVertical(10) - .PaddingHorizontal(20) - .Text("PAID") - .FontSize(52) - .Bold() - .FontColor(Colors.Green.Lighten2); - } - /// /// Composes the body of the invoice PDF: bill-to address block, job reference, alternating-row /// line-item table, and a right-aligned totals block that conditionally shows discount, tax,