Skip to content

Commit d1bb721

Browse files
ILLDEV-456 Use template for batch email sending
1 parent 712d3b9 commit d1bb721

3 files changed

Lines changed: 187 additions & 66 deletions

File tree

broker/scheduler/service/email_sender.go

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/indexdata/crosslink/broker/events"
1111
"github.com/indexdata/crosslink/broker/ill_db"
1212
pr_db "github.com/indexdata/crosslink/broker/patron_request/db"
13+
"github.com/indexdata/crosslink/broker/patron_request/proapi"
1314
psservice "github.com/indexdata/crosslink/broker/pullslip/service"
1415
"github.com/indexdata/go-utils/utils"
1516
)
@@ -20,6 +21,12 @@ var (
2021
MAX_RECORDS_PER_EMAIL = int32(utils.Must(utils.GetEnvInt("BATCH_PULLSLIP_MAX_COUNT", 100)))
2122
)
2223

24+
type pullslipEmailData struct {
25+
To []string `json:"to"`
26+
TemplateLabel string `json:"templateLabel"`
27+
IncludePdf bool `json:"includePdf"`
28+
}
29+
2330
type EmailSenderService struct {
2431
prRepo pr_db.PrRepo
2532
illRepo ill_db.IllRepo
@@ -85,11 +92,24 @@ func (s *EmailSenderService) generateAndEmailPullslip(ctx common.ExtendedContext
8592
if len(emailData.To) == 0 {
8693
return events.NewErrorResult("invalid email event data", "to field is required")
8794
}
88-
if emailData.Subject == "" {
89-
return events.NewErrorResult("invalid email event data", "subject field is required")
95+
if emailData.TemplateLabel == "" {
96+
return events.NewErrorResult("invalid email event data", "templateLabel field is required")
97+
}
98+
99+
template, err := s.prRepo.GetTemplateByPurposeAudienceLabelAndOwner(ctx, pr_db.GetTemplateByPurposeAudienceLabelAndOwnerParams{
100+
Owner: event.EventData.BatchActionData.Owner,
101+
Purpose: string(proapi.Email),
102+
Label: emailData.TemplateLabel,
103+
Audience: string(proapi.ModelActionParamsSendToStaff),
104+
})
105+
if err != nil {
106+
return events.NewErrorResult("failed to load email template", err.Error())
107+
}
108+
if !template.Subject.Valid || template.Subject.String == "" {
109+
return events.NewErrorResult("invalid email template", "subject field is required")
90110
}
91-
if emailData.Body == "" {
92-
return events.NewErrorResult("invalid email event data", "body field is required")
111+
if template.Body == "" {
112+
return events.NewErrorResult("invalid email template", "body field is required")
93113
}
94114

95115
prs, fullCount, err := s.prRepo.ListPatronRequests(ctx, pr_db.ListPatronRequestsParams{Limit: MAX_RECORDS_PER_EMAIL, Offset: 0}, pgcql)
@@ -114,31 +134,47 @@ func (s *EmailSenderService) generateAndEmailPullslip(ctx common.ExtendedContext
114134
pdfAttachment = &email.PdfAttach{Filename: "pull-slips.pdf", Data: pdfBytes}
115135
}
116136

117-
emailData.Body = strings.ReplaceAll(emailData.Body, "{{fullCount}}", fmt.Sprintf("%d", fullCount))
118-
emailData.Body = strings.ReplaceAll(emailData.Body, "{{actualCount}}", fmt.Sprintf("%d", len(prs)))
119-
emailData.Body = strings.ReplaceAll(emailData.Body, "{{batchQuery}}", event.EventData.BatchActionData.Selector)
137+
placeholders := map[string]string{
138+
"fullCount": fmt.Sprintf("%d", fullCount),
139+
"actualCount": fmt.Sprintf("%d", len(prs)),
140+
"batchQuery": event.EventData.BatchActionData.Selector,
141+
}
142+
messageData := email.EmailData{
143+
To: emailData.To,
144+
Subject: renderEmailTemplate(template.Subject.String, placeholders),
145+
Body: renderEmailTemplate(template.Body, placeholders),
146+
IsHTML: template.ContentType == string(proapi.Html),
147+
IncludePdf: emailData.IncludePdf,
148+
}
120149

121-
raw, err := email.BuildRawMessage(*owner.CustomData.FromEmail, emailData, pdfAttachment)
150+
raw, err := email.BuildRawMessage(*owner.CustomData.FromEmail, messageData, pdfAttachment)
122151
if err != nil {
123152
return events.NewErrorResult("failed to build email message", err.Error())
124153
}
125154

126-
err = s.emailService.SendEmail(*owner.CustomData.FromEmail, emailData.To, raw)
155+
err = s.emailService.SendEmail(*owner.CustomData.FromEmail, messageData.To, raw)
127156
if err != nil {
128157
return events.NewErrorResult("failed to send email via SMTP", err.Error())
129158
}
130159
return events.EventStatusSuccess, nil
131160
}
132161

133-
// extractEmailData retrieves EmailData from the event's CustomData map.
134-
func extractEmailData(eventData events.EventData) (email.EmailData, error) {
162+
func renderEmailTemplate(value string, placeholders map[string]string) string {
163+
for key, replacement := range placeholders {
164+
value = strings.ReplaceAll(value, "{{"+key+"}}", replacement)
165+
}
166+
return value
167+
}
168+
169+
// extractEmailData retrieves email pullslip parameters from the event's CustomData map.
170+
func extractEmailData(eventData events.EventData) (pullslipEmailData, error) {
135171
if eventData.CustomData == nil {
136-
return email.EmailData{}, fmt.Errorf("customData is nil")
172+
return pullslipEmailData{}, fmt.Errorf("customData is nil")
137173
}
138174

139175
toRaw, ok := eventData.CustomData["to"]
140176
if !ok {
141-
return email.EmailData{}, fmt.Errorf("missing 'to' field in customData")
177+
return pullslipEmailData{}, fmt.Errorf("missing 'to' field in customData")
142178
}
143179
var toAddrs []string
144180
switch v := toRaw.(type) {
@@ -148,24 +184,20 @@ func extractEmailData(eventData events.EventData) (email.EmailData, error) {
148184
for _, item := range v {
149185
s, ok := item.(string)
150186
if !ok {
151-
return email.EmailData{}, fmt.Errorf("'to' field contains non-string value")
187+
return pullslipEmailData{}, fmt.Errorf("'to' field contains non-string value")
152188
}
153189
toAddrs = append(toAddrs, s)
154190
}
155191
default:
156-
return email.EmailData{}, fmt.Errorf("'to' field has unexpected type %T", toRaw)
192+
return pullslipEmailData{}, fmt.Errorf("'to' field has unexpected type %T", toRaw)
157193
}
158194

159-
subject, _ := eventData.CustomData["subject"].(string)
160-
body, _ := eventData.CustomData["body"].(string)
161-
isHTML, _ := eventData.CustomData["isHtml"].(bool)
195+
templateLabel, _ := eventData.CustomData["templateLabel"].(string)
162196
includePdf, _ := eventData.CustomData["includePdf"].(bool)
163197

164-
return email.EmailData{
165-
To: toAddrs,
166-
Subject: subject,
167-
Body: body,
168-
IsHTML: isHTML,
169-
IncludePdf: includePdf,
198+
return pullslipEmailData{
199+
To: toAddrs,
200+
TemplateLabel: templateLabel,
201+
IncludePdf: includePdf,
170202
}, nil
171203
}

0 commit comments

Comments
 (0)