cmc-sales/go/internal/cmc/documents/purchase_order_builder.go

154 lines
4.4 KiB
Go
Raw Normal View History

package documents
import (
"bytes"
"fmt"
"html/template"
"path/filepath"
"strconv"
)
// PurchaseOrderLineItemTemplateData represents a PO line item for template rendering
type PurchaseOrderLineItemTemplateData struct {
Title string
Description template.HTML
Quantity string
UnitPrice float64
Discount float64
TotalPrice float64
}
// BuildPurchaseOrderHTML generates the complete HTML for a purchase order using templates
func (g *HTMLDocumentGenerator) BuildPurchaseOrderHTML(data *PurchaseOrderPDFData, totalPages int, currentPage int) string {
poNumber := data.PurchaseOrder.Title
// Calculate totals
subtotal := 0.0
lineItemsData := []PurchaseOrderLineItemTemplateData{}
for _, item := range data.LineItems {
unitPrice := 0.0
totalPrice := 0.0
discount := 0.0
if item.NetUnitPrice.Valid {
unitPrice, _ = strconv.ParseFloat(item.NetUnitPrice.String, 64)
}
if item.NetPrice.Valid {
totalPrice, _ = strconv.ParseFloat(item.NetPrice.String, 64)
subtotal += totalPrice
}
if item.DiscountAmountTotal.Valid {
discount, _ = strconv.ParseFloat(item.DiscountAmountTotal.String, 64)
}
lineItemsData = append(lineItemsData, PurchaseOrderLineItemTemplateData{
Title: item.Title,
Description: template.HTML(item.Description),
Quantity: item.Quantity,
UnitPrice: unitPrice,
Discount: discount,
TotalPrice: totalPrice,
})
}
gstAmount := 0.0
total := subtotal
if data.ShowGST {
gstAmount = subtotal * 0.1
total = subtotal + gstAmount
}
// Prepare template data
templateData := struct {
PONumber string
PrincipleName string
YourReference template.HTML
IssueDateString string
OrderedFrom template.HTML
DeliverTo template.HTML
DispatchBy string
ShippingInstructions template.HTML
CurrencyCode string
CurrencySymbol string
LineItems []PurchaseOrderLineItemTemplateData
Subtotal float64
GSTAmount float64
Total float64
ShowGST bool
LogoDataURI string
}{
PONumber: poNumber,
PrincipleName: data.Principle.Name,
YourReference: template.HTML(data.PurchaseOrder.PrincipleReference),
IssueDateString: data.IssueDateString,
OrderedFrom: template.HTML(data.PurchaseOrder.OrderedFrom),
DeliverTo: template.HTML(data.PurchaseOrder.DeliverTo),
DispatchBy: data.PurchaseOrder.DispatchBy,
ShippingInstructions: template.HTML(data.PurchaseOrder.ShippingInstructions),
CurrencyCode: data.CurrencyCode,
CurrencySymbol: data.CurrencySymbol,
LineItems: lineItemsData,
Subtotal: subtotal,
GSTAmount: gstAmount,
Total: total,
ShowGST: data.ShowGST,
LogoDataURI: g.loadLogo("quote_logo.png"),
}
// Define template functions
funcMap := template.FuncMap{
"formatPrice": func(price float64) template.HTML {
formatted := FormatPriceWithCommas(fmt.Sprintf("%.2f", price))
return template.HTML(fmt.Sprintf("%s%s", data.CurrencySymbol, formatted))
},
"formatTotal": func(amount float64) template.HTML {
formatted := FormatPriceWithCommas(fmt.Sprintf("%.2f", amount))
return template.HTML(fmt.Sprintf("%s%s", data.CurrencySymbol, formatted))
},
}
// Parse and execute template
possiblePathSets := [][]string{
{
filepath.Join("internal", "cmc", "documents", "templates", "purchase-order.html"),
filepath.Join("internal", "cmc", "documents", "templates", "header.html"),
},
{
filepath.Join("go", "internal", "cmc", "documents", "templates", "purchase-order.html"),
filepath.Join("go", "internal", "cmc", "documents", "templates", "header.html"),
},
{
filepath.Join("templates", "pdf", "purchase-order.html"),
filepath.Join("templates", "pdf", "header.html"),
},
{
"/app/templates/pdf/purchase-order.html",
"/app/templates/pdf/header.html",
},
}
var tmpl *template.Template
var err error
for _, pathSet := range possiblePathSets {
tmpl, err = template.New("purchase-order.html").Funcs(funcMap).ParseFiles(pathSet...)
if err == nil {
break
}
}
if tmpl == nil || err != nil {
fmt.Printf("Error parsing template from any path: %v\n", err)
return ""
}
var buf bytes.Buffer
if err := tmpl.Execute(&buf, templateData); err != nil {
fmt.Printf("Error executing template: %v\n", err)
return ""
}
return buf.String()
}