cmc-sales/go/internal/cmc/pdf/templates.go

317 lines
9.2 KiB
Go

package pdf
import (
"fmt"
"time"
"code.springupsoftware.com/cmc/cmc-sales/internal/cmc/db"
)
// QuotePDFData contains all data needed to generate a quote PDF
type QuotePDFData struct {
Document *db.Document
Quote interface{} // Quote specific data
Enquiry *db.Enquiry
Customer *db.Customer
Contact interface{} // Contact data
User *db.GetUserRow
LineItems []db.GetLineItemsTableRow
Currency interface{} // Currency data
CurrencySymbol string
ShowGST bool
CommercialComments string
}
// GenerateQuotePDF generates a PDF for a quote
func GenerateQuotePDF(data *QuotePDFData, outputDir string) (string, error) {
fmt.Printf("GenerateQuotePDF called with outputDir: %s\n", outputDir)
gen := NewGenerator(outputDir)
// First page with header
gen.AddPage()
gen.Page1Header()
// Extract data for details box
companyName := "" // TODO: Get from customer data
if data.Customer != nil {
companyName = data.Customer.Name
}
emailTo := "" // TODO: Get from contact
attention := "" // TODO: Get from contact
fromName := fmt.Sprintf("%s %s", data.User.FirstName, data.User.LastName)
fromEmail := data.User.Email
// Use CMC reference as the quote number
quoteNumber := data.Document.CmcReference
if data.Document.Revision > 0 {
quoteNumber = fmt.Sprintf("%s.%d", quoteNumber, data.Document.Revision)
}
yourReference := fmt.Sprintf("Enquiry on %s", data.Document.Created.Format("2 Jan 2006"))
issueDate := data.Document.Created.Format("2 January 2006")
// Add details box
gen.DetailsBox("QUOTE", companyName, emailTo, attention, fromName, fromEmail, quoteNumber, yourReference, issueDate)
// Add page content if any
// TODO: Add document pages content
gen.Page1Footer()
// Add pricing page
gen.AddPage()
gen.pdf.SetFont("Helvetica", "B", 14)
gen.pdf.CellFormat(0, 10, "PRICING & SPECIFICATIONS", "", 1, "C", false, 0, "")
gen.pdf.Ln(5)
// Convert line items
pdfItems := make([]LineItem, len(data.LineItems))
for i, item := range data.LineItems {
unitPrice := 0.0
totalPrice := 0.0
// Parse prices
if item.GrossUnitPrice.Valid {
fmt.Sscanf(item.GrossUnitPrice.String, "%f", &unitPrice)
}
if item.GrossPrice.Valid {
fmt.Sscanf(item.GrossPrice.String, "%f", &totalPrice)
}
pdfItems[i] = LineItem{
ItemNumber: item.ItemNumber,
Quantity: item.Quantity,
Title: item.Title,
UnitPrice: unitPrice,
TotalPrice: totalPrice,
}
}
// Add line items table
gen.AddLineItemsTable(pdfItems, data.CurrencySymbol, data.ShowGST)
// Add commercial comments if any
if data.CommercialComments != "" {
gen.pdf.Ln(10)
gen.pdf.SetFont("Helvetica", "B", 10)
gen.pdf.CellFormat(0, 5, "COMMERCIAL COMMENTS", "", 1, "L", false, 0, "")
gen.pdf.SetFont("Helvetica", "", 9)
gen.pdf.MultiCell(0, 5, data.CommercialComments, "", "L", false)
}
// TODO: Add terms and conditions page
// Generate filename
filename := quoteNumber
if data.Document.Revision > 0 {
filename = fmt.Sprintf("%s_%d.pdf", quoteNumber, data.Document.Revision)
} else {
filename = fmt.Sprintf("%s.pdf", quoteNumber)
}
// Save PDF
fmt.Printf("Saving PDF with filename: %s to outputDir: %s\n", filename, outputDir)
err := gen.Save(filename)
if err != nil {
fmt.Printf("Error saving PDF: %v\n", err)
} else {
fmt.Printf("PDF saved successfully: %s\n", filename)
}
return filename, err
}
// InvoicePDFData contains all data needed to generate an invoice PDF
type InvoicePDFData struct {
Document *db.Document
Invoice *db.Invoice
Enquiry *db.Enquiry
Customer *db.Customer
Job interface{} // Job data
LineItems []db.GetLineItemsTableRow
Currency interface{} // Currency data
CurrencySymbol string
ShowGST bool
ShipVia string
FOB string
IssueDate time.Time
}
// GenerateInvoicePDF generates a PDF for an invoice
func GenerateInvoicePDF(data *InvoicePDFData, outputDir string) (string, error) {
gen := NewGenerator(outputDir)
// First page with header
gen.AddPage()
gen.Page1Header()
// Extract data for details box
companyName := data.Customer.Name
emailTo := "" // TODO: Get from contact
attention := "" // TODO: Get from contact
fromName := "" // TODO: Get from user
fromEmail := "" // TODO: Get from user
invoiceNumber := data.Invoice.Title
yourReference := "" // TODO: Get reference
issueDate := data.IssueDate.Format("2 January 2006")
// Add details box
gen.DetailsBox("INVOICE", companyName, emailTo, attention, fromName, fromEmail, invoiceNumber, yourReference, issueDate)
// Add shipping details
gen.pdf.Ln(5)
gen.pdf.SetFont("Helvetica", "B", 10)
gen.pdf.CellFormat(30, 5, "Ship Via:", "", 0, "L", false, 0, "")
gen.pdf.SetFont("Helvetica", "", 10)
gen.pdf.CellFormat(60, 5, data.ShipVia, "", 1, "L", false, 0, "")
gen.pdf.SetFont("Helvetica", "B", 10)
gen.pdf.CellFormat(30, 5, "FOB:", "", 0, "L", false, 0, "")
gen.pdf.SetFont("Helvetica", "", 10)
gen.pdf.CellFormat(60, 5, data.FOB, "", 1, "L", false, 0, "")
gen.Page1Footer()
// Add line items page
gen.AddPage()
gen.pdf.SetFont("Helvetica", "B", 14)
gen.pdf.CellFormat(0, 10, "INVOICE DETAILS", "", 1, "C", false, 0, "")
gen.pdf.Ln(5)
// Convert line items
pdfItems := make([]LineItem, len(data.LineItems))
for i, item := range data.LineItems {
unitPrice := 0.0
totalPrice := 0.0
// Parse prices
if item.GrossUnitPrice.Valid {
fmt.Sscanf(item.GrossUnitPrice.String, "%f", &unitPrice)
}
if item.GrossPrice.Valid {
fmt.Sscanf(item.GrossPrice.String, "%f", &totalPrice)
}
pdfItems[i] = LineItem{
ItemNumber: item.ItemNumber,
Quantity: item.Quantity,
Title: item.Title,
UnitPrice: unitPrice,
TotalPrice: totalPrice,
}
}
// Add line items table
gen.AddLineItemsTable(pdfItems, data.CurrencySymbol, data.ShowGST)
// Generate filename
filename := fmt.Sprintf("%s.pdf", invoiceNumber)
// Save PDF
err := gen.Save(filename)
return filename, err
}
// PurchaseOrderPDFData contains all data needed to generate a purchase order PDF
type PurchaseOrderPDFData struct {
Document *db.Document
PurchaseOrder *db.PurchaseOrder
Principle *db.Principle
LineItems []db.GetLineItemsTableRow
Currency interface{} // Currency data
CurrencySymbol string
ShowGST bool
}
// GeneratePurchaseOrderPDF generates a PDF for a purchase order
func GeneratePurchaseOrderPDF(data *PurchaseOrderPDFData, outputDir string) (string, error) {
gen := NewGenerator(outputDir)
// First page with header
gen.AddPage()
gen.Page1Header()
// Extract data for details box
companyName := data.Principle.Name
emailTo := "" // TODO: Get from principle contact
attention := "" // TODO: Get from principle contact
fromName := "" // TODO: Get from user
fromEmail := "" // TODO: Get from user
poNumber := data.PurchaseOrder.Title
yourReference := data.PurchaseOrder.PrincipleReference
issueDate := data.PurchaseOrder.IssueDate.Format("Monday, 2 January 2006")
// Add details box
gen.DetailsBox("PURCHASE ORDER", companyName, emailTo, attention, fromName, fromEmail, poNumber, yourReference, issueDate)
// Add PO specific details
gen.pdf.Ln(5)
gen.pdf.SetFont("Helvetica", "B", 10)
gen.pdf.CellFormat(40, 5, "Ordered From:", "", 0, "L", false, 0, "")
gen.pdf.SetFont("Helvetica", "", 10)
gen.pdf.MultiCell(0, 5, data.PurchaseOrder.OrderedFrom, "", "L", false)
gen.pdf.SetFont("Helvetica", "B", 10)
gen.pdf.CellFormat(40, 5, "Dispatch By:", "", 0, "L", false, 0, "")
gen.pdf.SetFont("Helvetica", "", 10)
gen.pdf.CellFormat(0, 5, data.PurchaseOrder.DispatchBy, "", 1, "L", false, 0, "")
gen.pdf.SetFont("Helvetica", "B", 10)
gen.pdf.CellFormat(40, 5, "Deliver To:", "", 0, "L", false, 0, "")
gen.pdf.SetFont("Helvetica", "", 10)
gen.pdf.MultiCell(0, 5, data.PurchaseOrder.DeliverTo, "", "L", false)
if data.PurchaseOrder.ShippingInstructions != "" {
gen.pdf.SetFont("Helvetica", "B", 10)
gen.pdf.CellFormat(0, 5, "Shipping Instructions:", "", 1, "L", false, 0, "")
gen.pdf.SetFont("Helvetica", "", 10)
gen.pdf.MultiCell(0, 5, data.PurchaseOrder.ShippingInstructions, "", "L", false)
}
gen.Page1Footer()
// Add line items page
gen.AddPage()
gen.pdf.SetFont("Helvetica", "B", 14)
gen.pdf.CellFormat(0, 10, "ORDER DETAILS", "", 1, "C", false, 0, "")
gen.pdf.Ln(5)
// Convert line items
pdfItems := make([]LineItem, len(data.LineItems))
for i, item := range data.LineItems {
unitPrice := 0.0
totalPrice := 0.0
// Parse prices
if item.GrossUnitPrice.Valid {
fmt.Sscanf(item.GrossUnitPrice.String, "%f", &unitPrice)
}
if item.GrossPrice.Valid {
fmt.Sscanf(item.GrossPrice.String, "%f", &totalPrice)
}
pdfItems[i] = LineItem{
ItemNumber: item.ItemNumber,
Quantity: item.Quantity,
Title: item.Title,
UnitPrice: unitPrice,
TotalPrice: totalPrice,
}
}
// Add line items table
gen.AddLineItemsTable(pdfItems, data.CurrencySymbol, data.ShowGST)
// Generate filename
filename := poNumber
if data.Document.Revision > 0 {
filename = fmt.Sprintf("%s-Rev%d.pdf", data.PurchaseOrder.Title, data.Document.Revision)
} else {
filename = fmt.Sprintf("%s.pdf", data.PurchaseOrder.Title)
}
// Save PDF
err := gen.Save(filename)
return filename, err
}