Objective
- Stop PDF invoices from showing crossed-out prices, “Discount applied” copy, and discount savings when the customer did not receive a real promotion—especially on orders where internal pricing adjustments (travel rebalance, modifiers, overrides) were applied.
- Keep legitimate bundle and discount-code savings visible on invoices where those discounts actually apply.
- Align client-facing invoice PDFs with the total amount due teams expect, without misleading discount styling on individual lines.
Background
- Live example (RI5887): Travel-related admin-fee modifiers were used so total price would increase without affecting inspector commission. The total due looked correct on the client-facing side, but the PDF invoice showed the original amount crossed out with a lower amount beneath it (~$90), as if a customer discount had been applied.
- The team was not certain whether RI5887 was caused only by admin-fee modifier setup or by another pricing interaction on that order. Code review shows admin-only modifiers do not change customer
amount—they adjust admin/commission math inmodifierPriceCalc.ts. Misleading discount styling is driven by invoice display heuristics, not admin modifier evaluation itself. - Current invoice behavior: In
InvoicePDF.tsxandInvoiceAttachmentPDF.tsx, a charge line is treated as discounted whenoriginalBasePrice>amount, or when any discount metadata is present (discountAmount, bundle/code discount fields,_discountCodeId). Matching lines render strikethrough, a bold final amount, and generic “Discount applied” when no bundle/code name is available. - The same
originalBasePrice>amountstrikethrough appears on the workorder Charges & Payments table inServicesPayments.tsx(comment in PDF code says to keep in sync). - Surfaces: PDF download/preview via
InvoiceDrawer.tsx(tools workorder and client portal); email attachments via backendbuildTemplateEmailAttachments.tsusingInvoiceAttachmentPDF.tsx.
Product Decisions
Locked
- Problem type — This is incorrect customer-facing presentation on PDF invoices, not a request to change how admin modifiers calculate payroll.
- Legitimate discounts — Bundle and discount-code savings that are real customer promotions should continue to show appropriate discount styling on invoices when product confirms the attribution fields are populated.
- Template parity — Frontend
InvoicePDF.tsxand backendInvoiceAttachmentPDF.tsxmust stay aligned; both are in scope.
Open
- RI5887 trigger validation — Which charge fields on RI5887 caused the display (
originalBasePrice,amount,preTaxAmount,discountAmount, bundle/code IDs, modifier types on the service)? Needed to confirm whether the fix is display-only or also charge persistence. - Manual price overrides — When staff set a price override below list/modifier-calculated price, should the invoice show strikethrough/discount styling, a single flat amount, or something else?
- Charges & Payments table — Should the same discount-display fix apply to the workorder Charges & Payments strikethrough (
ServicesPayments.tsx), or PDF/email only in v1? - Generic “Discount applied” copy — When strikethrough is warranted, should generic fallback copy remain, or should strikethrough appear only when bundle name or discount code name is available?
originalBasePricevsamountcomparison —originalBasePriceis pre-tax starting fee;amountincludes tax. Should invoice discount detection require explicit discount fields (bundle/code/discountAmount) rather than any case where stored base exceeds final amount?
Scope
Frontend
- Invoice PDF (preview/download):
attik-frontend/src/components/invoice/InvoicePDF.tsx—getBaseOriginalTotal, per-linehasDiscount, strikethrough rendering, subtotal/savings section (showDiscountUI,totalSavings). - Invoice drawer entry points:
attik-frontend/src/components/invoice/InvoiceDrawer.tsx— used fromServicesPayments.tsx(tools) andJobAccordion.tsx(client portal). - Workorder charges table (likely same fix):
attik-frontend/src/app/tools/inspections/[id]/components/ServicesPayments.tsx—originalBasePrice > charge.amountstrikethrough; keep in sync with PDF per code comment.
Backend
- Email/PDF attachments:
attik-backend/src/util/functions/pdf/templates/InvoiceAttachmentPDF.tsx— duplicate discount logic; must match frontend fix. - Attachment builder:
attik-backend/src/util/functions/emailBuilder/buildTemplateEmailAttachments.ts— rendersInvoiceAttachmentPDFfor template emails.
Context (not modifier logic changes unless validation requires)
- Charge shape:
attik-backend/src/models/chargeSchema.ts—originalBasePrice,discountAmount, bundle/code discount fields,amount,preTaxAmount. - Charge creation:
attik-frontend/src/util/functions/quote/createChargeObjects.ts— setsoriginalBasePricefromstartingFee,amountfromtotalPrice/priceOverride. - Modifier evaluation:
attik-backend/src/util/functions/schedule/modifierPriceCalc.ts—addType: 'admin'affectsfinalAdminAdditiononly;addType: 'cost'affects customerfinalPrice. Display bug is separate from admin modifier math unless charge fields are written incorrectly on save.
Out of scope (unless product expands)
- Changing how admin, cost, or travel modifiers calculate prices or payroll.
- Client portal non-PDF pricing displays (unless tied to the same shared discount helper after PDF fix).
- ATT-1892 service-area travel modifier work—related operationally but separate delivery.
References
- Example order discussed: RI5887
attik-frontend/src/components/invoice/InvoicePDF.tsxattik-backend/src/util/functions/pdf/templates/InvoiceAttachmentPDF.tsxattik-frontend/src/app/tools/inspections/[id]/components/ServicesPayments.tsxattik-backend/src/util/functions/schedule/modifierPriceCalc.tsattik-frontend/src/util/functions/quote/createChargeObjects.ts