You are the Replit “AI Dev” agent working in the tcf-crm Repl.

──────────────────────────────────────── 📌 Goal ──────────────────────────────────────── Whenever an invoice’s status becomes "sent" on the /invoices page:

  1. Generate a PDF from the blank template filetemplates/TCF Supply LLC Invoice.pdf by programmatically filling all CRM invoice fields listed below.
  2. Save the filled PDF to /static/invoices/{invoice_number}.pdf.
  3. Email the PDF as an attachment to the Bill-To Email address (cc the internal [email protected] alias).
  4. Update the invoice record with pdf_url and sent_at timestamp.

──────────────────────────────────────── 🗂️ Field-to-PDF mapping ────────────────────────────────────────

Header

crm.invoice_number ➜ form_field("Invoice No") crm.created_at ➜ form_field("Date") crm.project ➜ form_field("Description") # optional multiline crm.due_date ➜ add text at top-right if present # extend template if needed

Bill-To section

crm.bill_to.name ➜ form_field("Bill To") crm.bill_to.email ➜ form_field("Billing Email") crm.bill_to.address ➜ form_field("Billing Address") crm.bill_to.phone ➜ form_field("Phone")

Ship-To section

crm.ship_to.attn ➜ form_field("Attn") crm.ship_to.address ➜ form_field("Address") crm.ship_to.city_state ➜ form_field("City/State") crm.ship_to.zip ➜ append to city_state OR extend template

Line-item table

For each slab in crm.line_items: slab.number ➜ column("Slab #(s)") slab.dimensions ➜ column("Dimensions") slab.qty ➜ column("Qty") slab.unit_price ➜ column("Unit Price") slab.line_total ➜ column("Line Total")

slab.location is stored internally; ignore unless template extended

Footer

crm.subtotal ➜ form_field("Subtotal") crm.discount ➜ form_field("Discount") crm.tcf_delivery ➜ form_field("TCF Delivery") crm.tax ➜ form_field("Sales Tax") crm.total_amount ➜ form_field("Total") crm.deposit_due ➜ form_field("Deposit Rcvd") crm.balance_due ➜ form_field("Amount Due")

──────────────────────────────────────── 🔧 Implementation hints ──────────────────────────────────────── • Use pdfrw or PyPDF2 + reportlab in Python; embed a scripts/generate_invoice_pdf.py with a render(invoice_id) function. • Register a DB trigger or server-side hook in routes/invoices.py that listens for status changes (PATCH /api/invoices/:id {status:"sent"}). • Configure SendGrid credentials via os.environ["SENDGRID_API_KEY"]; send email with subject Invoice {invoice_number} from TCF Supply. • Gracefully handle invoices with >17 line items by flowing onto page 2 using reportlab.platypus or adding “Page X of Y” footers. • Commit unit tests in tests/test_generate_invoice_pdf.py validating numeric formatting, tax calculations, and PDF existence.

Guarantee that existing React UI calls and JSON contract remain unchanged. Stop when the first PDF is successfully emailed and logged in the DB.