chore: always include both CSV and PDF in report ZIP instead of picking one format
This commit is contained in:
parent
517e95adc2
commit
1c9ab4554a
2 changed files with 33 additions and 48 deletions
|
|
@ -77,7 +77,6 @@ func (h *FileHandler) FileEvent(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
to := r.FormValue("email")
|
||||
format := r.FormValue("format")
|
||||
|
||||
if to == "" {
|
||||
log.Printf("ERROR [%s] handlers: FileEvent: missing email field",
|
||||
|
|
@ -85,12 +84,6 @@ func (h *FileHandler) FileEvent(w http.ResponseWriter, r *http.Request) {
|
|||
renderFileError(w, "Email address is required.")
|
||||
return
|
||||
}
|
||||
if format != "csv" && format != "pdf" {
|
||||
log.Printf("ERROR [%s] handlers: FileEvent: invalid format %q",
|
||||
time.Now().Format(time.RFC3339), format)
|
||||
renderFileError(w, "Format must be 'csv' or 'pdf'.")
|
||||
return
|
||||
}
|
||||
|
||||
// 3. Verify the authenticated user owns this event.
|
||||
userID := getUserID(r)
|
||||
|
|
@ -139,26 +132,27 @@ func (h *FileHandler) FileEvent(w http.ResponseWriter, r *http.Request) {
|
|||
userDept = reportUser.Department
|
||||
}
|
||||
|
||||
// 5. Generate the report in the requested format.
|
||||
var reportAttachment *email.Attachment
|
||||
switch format {
|
||||
case "csv":
|
||||
reportAttachment, err = generateCSV(event.Name, expenses, userName, userDept)
|
||||
case "pdf":
|
||||
reportAttachment, err = generatePDF(event.Name, expenses, userName, userDept)
|
||||
}
|
||||
// 5. Generate both CSV and PDF reports.
|
||||
csvAttachment, err := generateCSV(event.Name, expenses, userName, userDept)
|
||||
if err != nil {
|
||||
log.Printf("ERROR [%s] handlers: FileEvent: generate %s report: %v",
|
||||
time.Now().Format(time.RFC3339), format, err)
|
||||
renderFileError(w, "Failed to generate report. Please try again.")
|
||||
log.Printf("ERROR [%s] handlers: FileEvent: generate CSV: %v",
|
||||
time.Now().Format(time.RFC3339), err)
|
||||
renderFileError(w, "Failed to generate CSV report. Please try again.")
|
||||
return
|
||||
}
|
||||
pdfAttachment, err := generatePDF(event.Name, expenses, userName, userDept)
|
||||
if err != nil {
|
||||
log.Printf("ERROR [%s] handlers: FileEvent: generate PDF: %v",
|
||||
time.Now().Format(time.RFC3339), err)
|
||||
renderFileError(w, "Failed to generate PDF report. Please try again.")
|
||||
return
|
||||
}
|
||||
|
||||
// 6. Create a ZIP of all receipt images.
|
||||
zipAttachment, zipErr := createReceiptZip(event.Name, expenses)
|
||||
|
||||
// 7. Build the list of attachments (report + ZIP if available).
|
||||
attachments := []*email.Attachment{reportAttachment}
|
||||
// 7. Build the list of attachments (CSV + PDF + ZIP if available).
|
||||
attachments := []*email.Attachment{csvAttachment, pdfAttachment}
|
||||
if zipErr == nil && zipAttachment != nil {
|
||||
attachments = append(attachments, zipAttachment)
|
||||
} else if zipErr != nil {
|
||||
|
|
@ -219,11 +213,6 @@ func (h *FileHandler) GenerateReport(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
format := strings.ToLower(strings.TrimSpace(r.FormValue("format")))
|
||||
if format != "csv" && format != "pdf" {
|
||||
format = "pdf"
|
||||
}
|
||||
|
||||
userID := getUserID(r)
|
||||
if userID == "" {
|
||||
renderFileError(w, "Session expired. Please log in again.")
|
||||
|
|
@ -259,17 +248,19 @@ func (h *FileHandler) GenerateReport(w http.ResponseWriter, r *http.Request) {
|
|||
uDept = repUser.Department
|
||||
}
|
||||
|
||||
// Generate the report.
|
||||
var reportAtt *email.Attachment
|
||||
if format == "csv" {
|
||||
reportAtt, err = generateCSV(event.Name, expenses, uName, uDept)
|
||||
} else {
|
||||
reportAtt, err = generatePDF(event.Name, expenses, uName, uDept)
|
||||
}
|
||||
// Generate both CSV and PDF reports.
|
||||
csvAtt, err := generateCSV(event.Name, expenses, uName, uDept)
|
||||
if err != nil {
|
||||
log.Printf("ERROR [%s] handlers: GenerateReport: generate %s: %v",
|
||||
time.Now().Format(time.RFC3339), format, err)
|
||||
renderFileError(w, "Failed to generate report.")
|
||||
log.Printf("ERROR [%s] handlers: GenerateReport: generate CSV: %v",
|
||||
time.Now().Format(time.RFC3339), err)
|
||||
renderFileError(w, "Failed to generate CSV report.")
|
||||
return
|
||||
}
|
||||
pdfAtt, err := generatePDF(event.Name, expenses, uName, uDept)
|
||||
if err != nil {
|
||||
log.Printf("ERROR [%s] handlers: GenerateReport: generate PDF: %v",
|
||||
time.Now().Format(time.RFC3339), err)
|
||||
renderFileError(w, "Failed to generate PDF report.")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -277,8 +268,9 @@ func (h *FileHandler) GenerateReport(w http.ResponseWriter, r *http.Request) {
|
|||
var pkgBuf bytes.Buffer
|
||||
pkg := zip.NewWriter(&pkgBuf)
|
||||
|
||||
// Add report file.
|
||||
addToZip(pkg, reportAtt.Filename, reportAtt.Content)
|
||||
// Add both report files.
|
||||
addToZip(pkg, csvAtt.Filename, csvAtt.Content)
|
||||
addToZip(pkg, pdfAtt.Filename, pdfAtt.Content)
|
||||
|
||||
// Add receipt images directly (not nested).
|
||||
for i, exp := range expenses {
|
||||
|
|
@ -344,12 +336,10 @@ func (h *FileHandler) GenerateReport(w http.ResponseWriter, r *http.Request) {
|
|||
time.Now().Format(time.RFC3339), pkgFilename, eventID)
|
||||
|
||||
// Render the download/send fragment.
|
||||
ext := format
|
||||
reportName := fmt.Sprintf("%s-report.%s", sanitiseFilename(event.Name), ext)
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
fmt.Fprintf(w, `<div id="report-package" style="background: #064e3b; border: 1px solid #065f46; border-radius: 0.5rem; padding: 1rem; margin-top: 1rem;">
|
||||
<div style="font-weight: 600; color: #6ee7b7; margin-bottom: 0.5rem;">Report Ready</div>
|
||||
<p style="font-size: 0.8rem; color: var(--color-text-muted); margin-bottom: 0.75rem;">%s & %d receipt images packaged.</p>
|
||||
<p style="font-size: 0.8rem; color: var(--color-text-muted); margin-bottom: 0.75rem;">CSV + PDF report & %d receipt images packaged.</p>
|
||||
<div style="display: flex; gap: 0.5rem; margin-bottom: 0.75rem;">
|
||||
<a href="/dl/%s/%s" class="btn btn-primary" style="flex:1; text-align:center; text-decoration:none; font-size:0.85rem;" download>⬇ Download Now</a>
|
||||
</div>
|
||||
|
|
@ -364,7 +354,7 @@ func (h *FileHandler) GenerateReport(w http.ResponseWriter, r *http.Request) {
|
|||
<div id="send-link-result"></div>
|
||||
</div>
|
||||
</div>`,
|
||||
template.HTMLEscapeString(reportName), len(expenses),
|
||||
len(expenses),
|
||||
template.HTMLEscapeString(token), template.HTMLEscapeString(dlName),
|
||||
template.HTMLEscapeString(eventID), template.HTMLEscapeString(token))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,13 +135,8 @@
|
|||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label>Format</label>
|
||||
<div style="display: flex; gap: 1rem; margin-top: 0.25rem;">
|
||||
<label style="display: flex; align-items: center; gap: 0.25rem;">
|
||||
<input type="radio" name="format" value="csv"> CSV
|
||||
</label>
|
||||
<label style="display: flex; align-items: center; gap: 0.25rem;">
|
||||
<input type="radio" name="format" value="pdf" checked> PDF
|
||||
</label>
|
||||
<div style="display: flex; gap: 1rem; margin-top: 0.25rem; color: var(--color-text-muted); font-size: 0.85rem;">
|
||||
CSV + PDF (both included)
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
|
|||
Loading…
Reference in a new issue