Adding endpoint to disable reminders, fixing pdf attachment

This commit is contained in:
Finley Ghosh 2025-12-07 12:50:28 +11:00
parent bbdd035d04
commit b0a09c159d
3 changed files with 53 additions and 14 deletions

View file

@ -74,6 +74,7 @@ func main() {
// Quote routes
goRouter.HandleFunc("/quotes", quoteHandler.QuotesOutstandingView).Methods("GET")
goRouter.HandleFunc("/quotes/send-reminder", quoteHandler.SendManualReminder).Methods("POST")
goRouter.HandleFunc("/quotes/disable-reminders", quoteHandler.DisableReminders).Methods("POST")
// The following routes are currently disabled:
/*

View file

@ -65,20 +65,13 @@ func (es *EmailService) SendTemplateEmail(to string, subject string, templateNam
func (es *EmailService) SendTemplateEmailWithAttachments(to string, subject string, templateName string, data interface{}, ccs []string, bccs []string, attachments []interface{}) error {
// Convert interface{} attachments to []Attachment
var typedAttachments []Attachment
fmt.Printf("DEBUG: Received %d attachments to convert\n", len(attachments))
for i, att := range attachments {
fmt.Printf("DEBUG: Attachment %d type: %T\n", i, att)
for _, att := range attachments {
if a, ok := att.(Attachment); ok {
fmt.Printf("DEBUG: Converted to Attachment type: %s -> %s\n", a.Filename, a.FilePath)
typedAttachments = append(typedAttachments, a)
} else if a, ok := att.(struct{ Filename, FilePath string }); ok {
fmt.Printf("DEBUG: Converted from anonymous struct: %s -> %s\n", a.Filename, a.FilePath)
typedAttachments = append(typedAttachments, Attachment{Filename: a.Filename, FilePath: a.FilePath})
} else {
fmt.Printf("DEBUG: Failed to convert attachment type %T\n", att)
}
}
fmt.Printf("DEBUG: Final typed attachments count: %d\n", len(typedAttachments))
defaultBccs := []string{"carpis@cmctechnologies.com.au"}
bccs = append(defaultBccs, bccs...)

View file

@ -175,6 +175,7 @@ type QuoteQueries interface {
GetRecentlyExpiredQuotes(ctx context.Context, dateSUB interface{}) ([]db.GetRecentlyExpiredQuotesRow, error)
GetExpiringSoonQuotesOnDay(ctx context.Context, dateADD interface{}) ([]db.GetExpiringSoonQuotesOnDayRow, error)
GetRecentlyExpiredQuotesOnDay(ctx context.Context, dateSUB interface{}) ([]db.GetRecentlyExpiredQuotesOnDayRow, error)
DisableQuoteReminders(ctx context.Context, params db.DisableQuoteRemindersParams) (sql.Result, error)
}
type EmailSender interface {
@ -522,17 +523,16 @@ func (h *QuotesHandler) SendQuoteReminderEmailWithAttachment(ctx context.Context
// Copy PDF content to temp file
if _, err := io.Copy(tmpFile, resp.Body); err == nil {
type Attachment struct {
Filename string
FilePath string
}
attachments = []interface{}{
Attachment{
struct {
Filename string
FilePath string
}{
Filename: pdfFilename,
FilePath: tmpFile.Name(),
},
}
log.Printf("Successfully downloaded and attached PDF for quote %d: %s", quoteID, pdfFilename)
log.Printf("Successfully downloaded and attached PDF for quote %d: %s (tmpFile: %s)", quoteID, pdfFilename, tmpFile.Name())
} else {
log.Printf("Failed to copy PDF content for quote %d: %v", quoteID, err)
}
@ -685,6 +685,51 @@ func (h *QuotesHandler) SendManualReminder(w http.ResponseWriter, r *http.Reques
http.Redirect(w, r, "/go/quotes", http.StatusSeeOther)
}
// DisableReminders handles POST requests to disable automatic reminders for a quote
func (h *QuotesHandler) DisableReminders(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
// Parse form data
if err := r.ParseForm(); err != nil {
http.Error(w, "Invalid form data", http.StatusBadRequest)
return
}
quoteIDStr := r.FormValue("quote_id")
if quoteIDStr == "" {
http.Error(w, "Missing quote_id", http.StatusBadRequest)
return
}
quoteID, err := strconv.ParseInt(quoteIDStr, 10, 32)
if err != nil {
http.Error(w, "Invalid quote ID", http.StatusBadRequest)
return
}
// Get username from request
username := getUsername(r)
// Update the database to disable reminders
_, err = h.queries.DisableQuoteReminders(r.Context(), db.DisableQuoteRemindersParams{
RemindersDisabledBy: sql.NullString{String: username, Valid: true},
ID: int32(quoteID),
})
if err != nil {
log.Printf("Failed to disable reminders for quote %d: %v", quoteID, err)
http.Error(w, fmt.Sprintf("Failed to disable reminders: %v", err), http.StatusInternalServerError)
return
}
log.Printf("Reminders disabled for quote %d by %s", quoteID, username)
// Redirect back to quotes page
http.Redirect(w, r, "/go/quotes", http.StatusSeeOther)
}
// Helper: get reminder type as string
func reminderTypeString(reminderType int) string {
switch reminderType {