You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
290 lines
7.4 KiB
290 lines
7.4 KiB
package service |
|
|
|
import ( |
|
"bytes" |
|
"context" |
|
"fmt" |
|
"html/template" |
|
"time" |
|
|
|
"go-common/app/job/main/mcn/conf" |
|
"go-common/app/job/main/mcn/model" |
|
accgrpc "go-common/app/service/main/account/api" |
|
"go-common/library/log" |
|
"go-common/library/xstr" |
|
|
|
"github.com/pkg/errors" |
|
) |
|
|
|
// var . |
|
var ( |
|
// ErrNoAdminName no admin name |
|
ErrNoAdminName = errors.New("no admin name") |
|
|
|
tmplSignDueTitle *template.Template |
|
tmplSignDueContent *template.Template |
|
|
|
tmplPayDueTitle *template.Template |
|
tmplPayDueContent *template.Template |
|
) |
|
|
|
// use for template function call |
|
var funcHelper = template.FuncMap{ |
|
"Now": time.Now, |
|
} |
|
|
|
func (s *Service) initEmailTemplate() (err error) { |
|
if conf.Conf.MailTemplateConf.SignTmplTitle == "" || |
|
conf.Conf.MailTemplateConf.SignTmplContent == "" || |
|
conf.Conf.MailTemplateConf.PayTmplTitle == "" || |
|
conf.Conf.MailTemplateConf.PayTmplContent == "" { |
|
err = fmt.Errorf(`mail template conf is invalid, check mail-template.toml file, make sure all the following has value: |
|
TaskTmplContent |
|
TaskTmplTitle |
|
PayTmplContent |
|
PayTmplTitle`) |
|
return |
|
} |
|
tmplSignDueTitle, err = template.New("signTitle").Funcs(funcHelper).Parse(conf.Conf.MailTemplateConf.SignTmplTitle) |
|
if err != nil { |
|
log.Error("parse template fail, err=%v", err) |
|
return |
|
} |
|
|
|
tmplSignDueContent, err = template.New("signContent").Funcs(funcHelper).Parse(conf.Conf.MailTemplateConf.SignTmplContent) |
|
if err != nil { |
|
log.Error("parse template fail, err=%v", err) |
|
return |
|
} |
|
|
|
tmplPayDueTitle, err = template.New("payTitle").Funcs(funcHelper).Parse(conf.Conf.MailTemplateConf.PayTmplTitle) |
|
if err != nil { |
|
log.Error("parse template fail, err=%v", err) |
|
return |
|
} |
|
tmplPayDueContent, err = template.New("payContent").Funcs(funcHelper).Parse(conf.Conf.MailTemplateConf.PayTmplContent) |
|
if err != nil { |
|
log.Error("parse template fail, err=%v", err) |
|
return |
|
} |
|
return |
|
} |
|
|
|
// CheckDateDueCron . |
|
func (s *Service) CheckDateDueCron() { |
|
log.Info("start run CheckDateDueJob, date=%s", time.Now().Format(model.TimeFormatSec)) |
|
s.checkSignUpDue() |
|
log.Info("finish run CheckDateDueJob, date=%s", time.Now().Format(model.TimeFormatSec)) |
|
} |
|
|
|
type stateFunc func(context.Context, []int64) (int64, error) |
|
|
|
type emailData struct { |
|
IDs []int64 |
|
AdminName []string |
|
Data interface{} |
|
UpStateFunc stateFunc |
|
Title, Content *template.Template |
|
} |
|
|
|
func (e *emailData) addEmailDatas(es *[]*emailData) { |
|
*es = append(*es, e) |
|
} |
|
|
|
// buildEmail . |
|
func buildEmail(ids []int64, data interface{}, title, content *template.Template, upStateFunc stateFunc, adminName ...string) *emailData { |
|
return &emailData{ |
|
IDs: ids, |
|
Data: data, |
|
Title: title, |
|
Content: content, |
|
UpStateFunc: upStateFunc, |
|
AdminName: adminName, |
|
} |
|
} |
|
|
|
type dueData struct { |
|
Signs []*model.MCNSignInfo |
|
Pays []*model.SignPayInfo |
|
Sids, Pids []int64 |
|
} |
|
|
|
func (d *dueData) addSign(sign *model.MCNSignInfo) { |
|
d.Signs = append(d.Signs, sign) |
|
d.Sids = append(d.Sids, sign.SignID) |
|
} |
|
|
|
func (d *dueData) addPay(pay *model.SignPayInfo) { |
|
d.Pays = append(d.Pays, pay) |
|
d.Pids = append(d.Pids, pay.SignPayID) |
|
} |
|
|
|
func (d *dueData) addName(infoMap map[int64]*accgrpc.Info) { |
|
for _, v := range d.Signs { |
|
v.McnName = getName(infoMap, v.McnMid) |
|
} |
|
for _, v := range d.Pays { |
|
v.McnName = getName(infoMap, v.McnMid) |
|
} |
|
} |
|
|
|
// func getOrCreate(dataMap map[string]*dueData, key string) *dueData { |
|
// var data, ok = dataMap[key] |
|
// if !ok { |
|
// data = &dueData{} |
|
// dataMap[key] = data |
|
// } |
|
// return data |
|
// } |
|
|
|
func getName(infoMap map[int64]*accgrpc.Info, mid int64) string { |
|
if info, ok := infoMap[mid]; ok { |
|
return info.Name |
|
} |
|
return "" |
|
} |
|
|
|
func (s *Service) checkSignUpDue() { |
|
var ( |
|
mids []int64 |
|
emailDatas []*emailData |
|
data = &dueData{} |
|
c = context.Background() |
|
infoMap map[int64]*accgrpc.Info |
|
) |
|
// 30天内到期 sign |
|
listDue, err := s.dao.McnSignDues(c) |
|
if err != nil { |
|
log.Error("s.dao.McnSignDues error(%+v)", err) |
|
return |
|
} |
|
for _, v := range listDue { |
|
mids = append(mids, v.McnMid) |
|
data.addSign(v) |
|
} |
|
// 7天内到期的pay |
|
listPayDue, err := s.dao.McnSignPayDues(c) |
|
if err != nil { |
|
log.Error("s.dao.McnSignPayDues error(%+v)", err) |
|
return |
|
} |
|
for _, v := range listPayDue { |
|
mids = append(mids, v.McnMid) |
|
data.addPay(v) |
|
} |
|
mids = uniqNoEmpty(mids) |
|
infosReply, err := s.accGRPC.Infos3(c, &accgrpc.MidsReq{Mids: mids}) |
|
if err != nil { |
|
log.Error("s.accGRPC.Infos3(%s) error(%+v)", xstr.JoinInts(mids), err) |
|
err = nil |
|
} else { |
|
infoMap = infosReply.Infos |
|
} |
|
emailDatas = make([]*emailData, 0) |
|
data.addName(infoMap) |
|
buildEmail(data.Sids, data.Signs, tmplSignDueTitle, tmplSignDueContent, s.dao.UpMcnSignEmailState, conf.Conf.MailConf.DueAuthorityGroups...).addEmailDatas(&emailDatas) |
|
buildEmail(data.Pids, data.Pays, tmplPayDueTitle, tmplPayDueContent, s.dao.UpMcnSignPayEmailState, conf.Conf.MailConf.DueAuthorityGroups...).addEmailDatas(&emailDatas) |
|
for _, e := range emailDatas { |
|
s.doSendEmailFunc(c, e) |
|
} |
|
} |
|
|
|
func (s *Service) doSendEmailFunc(c context.Context, e *emailData) { |
|
s.worker.Do(c, func(c context.Context) { |
|
if len(e.IDs) == 0 { |
|
log.Warn("not need to update") |
|
return |
|
} |
|
var err error |
|
if err = s.sendMailWithTemplate(e.Data, e.Title, e.Content, e.AdminName...); err != nil { |
|
log.Error("s.sendMailWithTemplate(%+v,%+v,%+v,%+v) error(%+v)", e.Data, e.Title, e.Content, e.AdminName, err) |
|
return |
|
} |
|
if _, err = e.UpStateFunc(c, e.IDs); err != nil { |
|
log.Error("upfunc(%+v,%s) error(%+v)", e.UpStateFunc, xstr.JoinInts(e.IDs), err) |
|
return |
|
} |
|
log.Info("func(%s) update succ", xstr.JoinInts(e.IDs)) |
|
}) |
|
} |
|
|
|
// data, data to generate email content |
|
// contentTmpl, template to generate email content |
|
// adminname, slice for all admin name |
|
// |
|
func (s *Service) sendMailWithTemplate(data interface{}, subjectTmpl, contentTmpl *template.Template, adminName ...string) (err error) { |
|
if contentTmpl == nil { |
|
err = fmt.Errorf("template for email is nil, data=%+v", data) |
|
log.Error("%s", err) |
|
return |
|
} |
|
|
|
var contentBuf = bytes.NewBuffer(nil) |
|
err = contentTmpl.Execute(contentBuf, data) |
|
if err != nil { |
|
log.Error("template fail to execute, err=%v", err) |
|
return |
|
} |
|
|
|
var subjectBuf = bytes.NewBuffer(nil) |
|
err = subjectTmpl.Execute(subjectBuf, data) |
|
if err != nil { |
|
log.Error("template fail to execute, err=%v", err) |
|
return |
|
} |
|
|
|
var addrs []string |
|
for _, v := range adminName { |
|
if v == "" { |
|
log.Warn("admin name is empty") |
|
continue |
|
} |
|
addrs = append(addrs, v) |
|
} |
|
|
|
if len(addrs) == 0 { |
|
log.Error("admin name is empty, cannot send email, data=%+v", data) |
|
err = ErrNoAdminName |
|
return |
|
} |
|
if err = s.dao.SendMail(contentBuf.String(), subjectBuf.String(), addrs); err != nil { |
|
log.Error("s.dao.SendMail(%s,%s,%+v) error(%+v)", contentBuf.String(), subjectBuf.String(), addrs, err) |
|
return |
|
} |
|
log.Info("email send succ, sub=%s, admin=%s", subjectBuf.String(), adminName) |
|
return |
|
} |
|
|
|
func chain(ids ...[]int64) []int64 { |
|
res := make([]int64, 0, len(ids)) |
|
for _, l := range ids { |
|
res = append(res, l...) |
|
} |
|
return res |
|
} |
|
|
|
// func uniq(ids ...[]int64) []int64 { |
|
// hm := make(map[int64]struct{}) |
|
// for _, i := range chain(ids...) { |
|
// hm[i] = struct{}{} |
|
// } |
|
// res := make([]int64, 0, len(ids)) |
|
// for i := range hm { |
|
// res = append(res, i) |
|
// } |
|
// return res |
|
// } |
|
|
|
func uniqNoEmpty(ids ...[]int64) []int64 { |
|
hm := make(map[int64]struct{}) |
|
for _, i := range chain(ids...) { |
|
hm[i] = struct{}{} |
|
} |
|
res := make([]int64, 0, len(ids)) |
|
for i := range hm { |
|
if i > 0 { |
|
res = append(res, i) |
|
} |
|
} |
|
return res |
|
}
|
|
|