package pdf import ( "bytes" "fmt" "html/template" "path/filepath" "strconv" ) // OrderAckLineItemTemplateData represents an order ack line item for template rendering type OrderAckLineItemTemplateData struct { Title string Description template.HTML Quantity string UnitPrice float64 Discount float64 TotalPrice float64 } // BuildOrderAckHTML generates the complete HTML for an order acknowledgement using templates func (g *HTMLDocumentGenerator) BuildOrderAckHTML(data *OrderAckPDFData, totalPages int, currentPage int) string { orderAckNumber := data.OrderAcknowledgement.CmcReference // Calculate totals subtotal := 0.0 lineItemsData := []OrderAckLineItemTemplateData{} for _, item := range data.LineItems { unitPrice := 0.0 totalPrice := 0.0 discount := 0.0 if item.GrossUnitPrice.Valid { unitPrice, _ = strconv.ParseFloat(item.GrossUnitPrice.String, 64) } if item.GrossPrice.Valid { totalPrice, _ = strconv.ParseFloat(item.GrossPrice.String, 64) subtotal += totalPrice } if item.DiscountAmountTotal.Valid { discount, _ = strconv.ParseFloat(item.DiscountAmountTotal.String, 64) } lineItemsData = append(lineItemsData, OrderAckLineItemTemplateData{ 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 { OrderAckNumber string CompanyName string EmailTo string Attention string IssueDateString string YourReference string JobTitle string BillTo string ShipTo string ShipVia string FOB string PaymentTerms string CurrencyCode string CurrencySymbol string LineItems []OrderAckLineItemTemplateData Subtotal float64 GSTAmount float64 Total float64 ShowGST bool LogoDataURI string }{ OrderAckNumber: orderAckNumber, CompanyName: data.Customer.Name, EmailTo: data.EmailTo, Attention: data.Attention, IssueDateString: data.IssueDateString, YourReference: data.YourReference, JobTitle: data.JobTitle, BillTo: data.BillTo, ShipTo: data.ShipTo, ShipVia: data.ShipVia, FOB: data.FOB, PaymentTerms: data.PaymentTerms, 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", "order-acknowledgement.html"), filepath.Join("internal", "cmc", "documents", "templates", "header.html"), }, { filepath.Join("go", "internal", "cmc", "documents", "templates", "order-acknowledgement.html"), filepath.Join("go", "internal", "cmc", "documents", "templates", "header.html"), }, { filepath.Join("templates", "pdf", "order-acknowledgement.html"), filepath.Join("templates", "pdf", "header.html"), }, { "/app/templates/pdf/order-acknowledgement.html", "/app/templates/pdf/header.html", }, } var tmpl *template.Template var err error for _, pathSet := range possiblePathSets { tmpl, err = template.New("order-acknowledgement.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() }