From 3bfaa5b0fdc08434f966fc6cf8a793b7cfb8f6ec Mon Sep 17 00:00:00 2001
From: Finley Ghosh
Date: Mon, 19 Jan 2026 17:52:57 +1100
Subject: [PATCH] Supporting quote generation
---
go/internal/cmc/handlers/pdf_api.go | 11 ++--
go/internal/cmc/pdf/html_generator.go | 21 +++++++
php/app/controllers/documents_controller.php | 63 ++++++++-----------
php/app/vendors/pagecounter.php | 3 +-
.../views/documents/generate_first_page.ctp | 34 +++-------
php/app/views/documents/pdf_invoice.ctp | 57 ++++++++++++++++-
php/app/views/documents/pdf_quote.ctp | 43 ++++++++++---
7 files changed, 155 insertions(+), 77 deletions(-)
diff --git a/go/internal/cmc/handlers/pdf_api.go b/go/internal/cmc/handlers/pdf_api.go
index c9ee797f..563454b4 100644
--- a/go/internal/cmc/handlers/pdf_api.go
+++ b/go/internal/cmc/handlers/pdf_api.go
@@ -610,12 +610,15 @@ func CountPages(w http.ResponseWriter, r *http.Request) {
return
}
- log.Printf("CountPages: Attempting to count pages for file: %s", req.FilePath)
+ // Normalize path: remove double slashes
+ normalizedPath := strings.ReplaceAll(req.FilePath, "//", "/")
+
+ log.Printf("CountPages: Attempting to count pages for file: %s", normalizedPath)
// Count pages in the PDF file
- pageCount, err := pdf.CountPDFPages(req.FilePath)
+ pageCount, err := pdf.CountPDFPages(normalizedPath)
if err != nil {
- log.Printf("CountPages: error counting pages in %s: %v", req.FilePath, err)
+ log.Printf("CountPages: error counting pages in %s: %v", normalizedPath, err)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_ = json.NewEncoder(w).Encode(map[string]interface{}{
@@ -625,7 +628,7 @@ func CountPages(w http.ResponseWriter, r *http.Request) {
return
}
- log.Printf("CountPages: Successfully counted %d pages in %s", pageCount, req.FilePath)
+ log.Printf("CountPages: Successfully counted %d pages in %s", pageCount, normalizedPath)
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]int{"page_count": pageCount})
}
diff --git a/go/internal/cmc/pdf/html_generator.go b/go/internal/cmc/pdf/html_generator.go
index c3cdce05..58eb1835 100644
--- a/go/internal/cmc/pdf/html_generator.go
+++ b/go/internal/cmc/pdf/html_generator.go
@@ -102,6 +102,7 @@ func (g *HTMLDocumentGenerator) GenerateInvoicePDF(data *InvoicePDFData) (string
}
filename := fmt.Sprintf("%s.pdf", filenameBase)
pdfPath := filepath.Join(g.outputDir, filename)
+ fmt.Printf("=== HTML Generator: Invoice filename generation - invoiceNumber='%s', filenameBase='%s', final filename='%s' ===\n", invoiceNumber, filenameBase, filename)
if err := g.htmlToPDF(tempHTML, pdfPath); err != nil {
return "", fmt.Errorf("failed to convert HTML to PDF (second pass): %w", err)
@@ -195,6 +196,10 @@ func (g *HTMLDocumentGenerator) GenerateQuotePDF(data *QuotePDFData) (string, er
if data.Document != nil {
log.Printf("=== HTML Generator: Document not nil, CmcReference='%s'", data.Document.CmcReference)
quoteNumber = data.Document.CmcReference
+ if quoteNumber == "" {
+ // Strong fallback so we never emit a leading underscore filename
+ quoteNumber = fmt.Sprintf("Quote-%d", data.Document.ID)
+ }
if data.Document.Revision > 0 {
quoteNumber = fmt.Sprintf("%s_%d", quoteNumber, data.Document.Revision)
}
@@ -224,11 +229,27 @@ func (g *HTMLDocumentGenerator) GenerateQuotePDF(data *QuotePDFData) (string, er
tempMergedPath := filepath.Join(g.outputDir, fmt.Sprintf("%s_merged_temp.pdf", filenameBase))
if err := MergePDFs(pdfPath, termsPath, tempMergedPath); err != nil {
fmt.Printf("=== HTML Generator: Warning - could not merge T&C PDF: %v. Returning quote without T&C.\n", err)
+ fmt.Printf("=== HTML Generator: Checking if pdfPath exists: %s\n", pdfPath)
+ if stat, err := os.Stat(pdfPath); err == nil {
+ fmt.Printf("=== HTML Generator: pdfPath exists, size=%d bytes\n", stat.Size())
+ }
return filename, nil
}
+ fmt.Printf("=== HTML Generator: Merge succeeded, replacing original PDF\n")
// Replace original with merged version
if err := os.Rename(tempMergedPath, pdfPath); err != nil {
fmt.Printf("=== HTML Generator: Warning - could not replace PDF: %v\n", err)
+ fmt.Printf("=== HTML Generator: tempMergedPath: %s\n", tempMergedPath)
+ fmt.Printf("=== HTML Generator: pdfPath: %s\n", pdfPath)
+ } else {
+ fmt.Printf("=== HTML Generator: Replaced PDF successfully\n")
+ }
+
+ // Verify the final file exists
+ if stat, err := os.Stat(pdfPath); err == nil {
+ fmt.Printf("=== HTML Generator: Final PDF verified, size=%d bytes\n", stat.Size())
+ } else {
+ fmt.Printf("=== HTML Generator: ERROR - Final PDF does not exist after merge: %v\n", err)
}
}
diff --git a/php/app/controllers/documents_controller.php b/php/app/controllers/documents_controller.php
index bbaa8b36..fe147f5d 100755
--- a/php/app/controllers/documents_controller.php
+++ b/php/app/controllers/documents_controller.php
@@ -867,19 +867,27 @@ ENDINSTRUCTIONS;
//
switch($docType) {
case "quote":
- // Use enquiry title, or fall back to cmc_reference, or document ID
- if (!empty($enquiry['Enquiry']['title'])) {
- $filename = $enquiry['Enquiry']['title'];
- } elseif (!empty($document['Document']['cmc_reference'])) {
- $filename = $document['Document']['cmc_reference'];
- } else {
- $filename = 'Quote-' . $document['Document']['id'];
- }
+ // Use enquiry title, or fall back to cmc_reference, or document ID
+ if (!empty($enquiry['Enquiry']['title'])) {
+ $filename = $enquiry['Enquiry']['title'];
+ } elseif (!empty($document['Document']['cmc_reference'])) {
+ $filename = $document['Document']['cmc_reference'];
+ } else {
+ $filename = 'Quote-' . $document['Document']['id'];
+ }
+ $this->set('docTitle', $enquiry['Enquiry']['title']);
+ $this->set('job', $job);
+ $this->set('issue_date_string', date('d F Y', strtotime($document['Quote']['issue_date'])));
+ $this->set('ship_via', $document['Quote']['ship_via']);
+ $this->set('fob', $document['Quote']['fob']);
+ $template_name = 'pdf_quote';
+ break;
+
+ case "invoice":
$filename = $document['Invoice']['title'];
$this->set('docTitle', $document['Invoice']['title']);
$this->set('job', $this->Document->Invoice->Job->find('first', array('conditions'=>array('Job.id'=>$document['Invoice']['job_id']))));
$this->set('issue_date_string', date('d F Y', strtotime($document['Invoice']['issue_date'])));
-
$this->set('ship_via', $document['Invoice']['ship_via']);
$this->set('fob', $document['Invoice']['fob']);
$template_name = 'pdf_invoice';
@@ -948,34 +956,15 @@ ENDINSTRUCTIONS;
break;
}
- if($document['Document']['revision'] > 0) {
- $filename = $filename.'_'.$document['Document']['revision'].'.pdf';
- }
- else {
- $filename = $filename.'.pdf';
- }
-
- $this->set('filename', $filename);
- $document['Document']['pdf_filename'] = $filename;
- $document['Document']['pdf_created_at'] = date('Y-m-d H:i:s');
- $document['Document']['pdf_created_by_user_id'] = $this->getCurrentUserID();
- if($this->Document->save($document)) {
- //echo "Set pdf_filename attritbute to: ".$filename;
-
- // Count pages and update doc_page_count
- App::import('Vendor','pagecounter');
- $pageCounter = new PageCounter();
- $pdfPath = $pdf_dir . $filename;
- $pageCount = $pageCounter->count($pdfPath);
- if ($pageCount > 0) {
- $this->Document->id = $document['Document']['id'];
- $this->Document->saveField('doc_page_count', $pageCount);
- }
- }
- else {
- //echo 'Failed to set pdf_filename to: '.$filename;
- }
-
+ // Don't set filename here - let the Go service and view handle it
+ // The filename will be set by the pdf_* view after Go generates the PDF
+
+ $this->set('filename', '');
+ $this->set('docType', $docType);
+ $this->set('docTypeFullName', strtoupper($docTypeFullName));
+ $this->set('currency',$currency);
+ $this->set('currencyCode', isset($currencyCode) ? $currencyCode : 'AUD');
+ $this->set('currencySymbol', isset($currencySymbol) ? $currencySymbol : '$');
$colWidths = array(
'item' => '7%',
diff --git a/php/app/vendors/pagecounter.php b/php/app/vendors/pagecounter.php
index b0d4c10d..2c42e53e 100755
--- a/php/app/vendors/pagecounter.php
+++ b/php/app/vendors/pagecounter.php
@@ -9,7 +9,7 @@ class PageCounter {
* Returns the page count or null if unable to determine.
*/
function count($file) {
- error_log("PageCounter: Attempting to count pages for file: $file");
+ error_log("PageCounter: START - Attempting to count pages for file: $file");
if (!file_exists($file) || !is_readable($file)) {
error_log("PageCounter: File does not exist or is not readable: $file");
@@ -17,6 +17,7 @@ class PageCounter {
}
try {
+ error_log("PageCounter: File exists and is readable, calling getGoBaseUrlOrFail()");
// Get the Go base URL from config
App::import('Controller', 'App');
$appController = new AppController();
diff --git a/php/app/views/documents/generate_first_page.ctp b/php/app/views/documents/generate_first_page.ctp
index 599b2616..5a7fc8ac 100755
--- a/php/app/views/documents/generate_first_page.ctp
+++ b/php/app/views/documents/generate_first_page.ctp
@@ -42,39 +42,23 @@ $pagecounter = new PageCounter();
count($attachmentPath);
- $pagecount = '('.$count.' pages)';
- file_put_contents($debugPath, "Count result: {$count}\n---\n", FILE_APPEND);
- } else {
- file_put_contents($debugPath, "Skipped (non-pdf)\n---\n", FILE_APPEND);
+ if ($count !== null && $count > 0) {
+ $pagecount = '(' . $count . ' pages)';
+ } else {
+ $pagecount = '(page count unavailable)';
+ }
}
?>
= $attachment['Attachment']['name']; ?> = $pagecount ?>
diff --git a/php/app/views/documents/pdf_invoice.ctp b/php/app/views/documents/pdf_invoice.ctp
index 9ee39df1..555a8cc8 100755
--- a/php/app/views/documents/pdf_invoice.ctp
+++ b/php/app/views/documents/pdf_invoice.ctp
@@ -1,8 +1,17 @@
= 300) {
@@ -123,9 +135,50 @@ if ($httpCode < 200 || $httpCode >= 300) {
echo "
";
exit;
}
-?>
+// PDF generated successfully - capture the filename from Go and save to database
+$result = json_decode($response, true);
+if (isset($result['filename'])) {
+ $Document = ClassRegistry::init('Document');
+ $Document->id = $document['Document']['id'];
+ $Document->saveField('pdf_filename', $result['filename']);
+ $Document->saveField('pdf_created_at', date('Y-m-d H:i:s'));
+
+ // Get user ID safely
+ $userId = null;
+ if (isset($this->Session)) {
+ $userId = $this->Session->read('Auth.User.id');
+ }
+ if ($userId) {
+ $Document->saveField('pdf_created_by_user_id', $userId);
+ }
+
+ // Count pages using the Go service
+ App::import('Vendor','pagecounter');
+ $pageCounter = new PageCounter();
+ $pdfPath = $outputDir . '/' . $result['filename'];
+ error_log("=== pdf_invoice.ctp: Counting pages for PDF: " . $pdfPath . " ===");
+ $pageCount = $pageCounter->count($pdfPath);
+ error_log("=== pdf_invoice.ctp: Page count result: " . var_export($pageCount, true) . " ===");
+ if ($pageCount !== null && $pageCount > 0) {
+ $Document->saveField('doc_page_count', $pageCount);
+ error_log("=== pdf_invoice.ctp: Saved page count: " . $pageCount . " ===");
+ } else {
+ error_log("=== pdf_invoice.ctp: Page count was null or 0, not saving ===");
+ }
+}
+
+error_log("=== pdf_invoice.ctp: About to redirect to /documents/view/" . $document['Document']['id'] . " ===");
+?>
+
+
+
+
+
+
+PDF generated successfully. Click here if you are not redirected.
-
+
+
\ No newline at end of file
diff --git a/php/app/views/documents/pdf_quote.ctp b/php/app/views/documents/pdf_quote.ctp
index 3d84b9b1..5dc82569 100755
--- a/php/app/views/documents/pdf_quote.ctp
+++ b/php/app/views/documents/pdf_quote.ctp
@@ -92,10 +92,30 @@ if ($httpCode < 200 || $httpCode >= 300) {
exit;
}
-// PDF generated successfully - now count pages and update database
+// PDF generated successfully - now save metadata and count pages
$result = json_decode($response, true);
if (isset($result['filename'])) {
+ // Build path, removing any double slashes
$pdfPath = $outputDir . '/' . $result['filename'];
+ $pdfPath = preg_replace('#/+#', '/', $pdfPath);
+
+ // Update database with PDF metadata
+ $Document = ClassRegistry::init('Document');
+ $Document->id = $document['Document']['id'];
+ $Document->saveField('pdf_filename', $result['filename']);
+ $Document->saveField('pdf_created_at', date('Y-m-d H:i:s'));
+
+ // Get user ID safely (match invoice logic)
+ $userId = null;
+ if (isset($this->Session)) {
+ $userId = $this->Session->read('Auth.User.id');
+ }
+ if (!$userId && isset($_SESSION['Auth']['User']['id'])) {
+ $userId = $_SESSION['Auth']['User']['id'];
+ }
+ if ($userId) {
+ $Document->saveField('pdf_created_by_user_id', $userId);
+ }
// Count pages using the Go service
App::import('Vendor','pagecounter');
@@ -103,14 +123,21 @@ if (isset($result['filename'])) {
$pageCount = $pageCounter->count($pdfPath);
if ($pageCount > 0) {
- // Update the document with the page count
- $Document = ClassRegistry::init('Document');
- $Document->id = $document['Document']['id'];
$Document->saveField('doc_page_count', $pageCount);
}
}
?>
-
-
\ No newline at end of file
+
+
+
+
+ Redirecting...
+
+
+ PDF generated successfully. Redirecting back to quote...
+ Click here if not redirected
+
+
+
\ No newline at end of file