Skip to content
Snippets Groups Projects
Commit cb588f75 authored by meskio's avatar meskio :tent:
Browse files

Add email order notifications

parent 7e61b120
Branches
No related tags found
No related merge requests found
......@@ -11,6 +11,7 @@ import (
type api struct {
db *gorm.DB
signKey []byte
mail *Mail
}
func initDB(dbPath string) (*gorm.DB, error) {
......@@ -24,13 +25,13 @@ func initDB(dbPath string) (*gorm.DB, error) {
return db, err
}
func Init(dbPath string, signKey string, r *mux.Router) error {
func Init(dbPath string, signKey string, mail *Mail, r *mux.Router) error {
db, err := initDB(dbPath)
if err != nil {
return err
}
a := api{db, []byte(signKey)}
a := api{db, []byte(signKey), mail}
go a.refundOrders()
token, err := a.newToken(0, "admin", false)
......
......@@ -47,7 +47,8 @@ func newTestAPI(t *testing.T) *testAPI {
dbPath := path.Join(testPath, "test.db")
r := mux.NewRouter()
err = Init(dbPath, signKey, r)
mail := NewMail("", "", "")
err = Init(dbPath, signKey, mail, r)
if err != nil {
t.Fatal("Init error:", err)
}
......
package api
import (
"bytes"
"net/smtp"
"strings"
"text/template"
)
const (
orderTmpl = `To: {{.To}}
From: {{.From}}
Content-Type: text/plain; charset="utf-8"
Subject: [garbanzo] pedido {{.Name}}
El pedido {{.Name}} a sido cerrado.
Se han pedido:{{range $name, $amount := .Products}}
* {{$name}}: {{$amount}}{{end}}
Las siguientes personas han pedido:
{{range $name, $purchases := .Purchases}}
{{$name}}:{{range $purchases}}
* {{.Product.Name}}: {{.Amount}}{{end}}
{{end}}
`
)
type Mail struct {
auth smtp.Auth
server string
email string
tmpl *template.Template
}
func NewMail(email, password, server string) *Mail {
hostname := strings.Split(server, ":")[0]
username := strings.Split(email, "@")[0]
tmpl := template.Must(template.New("order").Parse(orderTmpl))
return &Mail{
auth: smtp.PlainAuth("", username, password, hostname),
server: server,
email: email,
tmpl: tmpl,
}
}
type orderData struct {
To string
From string
Name string
Products map[string]int
Purchases map[string][]OrderPurchase
}
func (m Mail) sendOrder(to string, order *Order) error {
if m.server == "" {
return nil
}
products := make(map[string]int)
purchases := make(map[string][]OrderPurchase)
for _, t := range order.Transactions {
var purchase []OrderPurchase
for _, p := range t.OrderPurchase {
if p.Amount == 0 {
continue
}
products[p.Product.Name] += p.Amount
purchase = append(purchase, p)
}
purchases[t.Member.Name] = purchase
}
data := orderData{
To: to,
From: m.email,
Name: order.Name,
Products: products,
Purchases: purchases,
}
var buff bytes.Buffer
err := m.tmpl.ExecuteTemplate(&buff, "order", data)
if err != nil {
return err
}
return smtp.SendMail(m.server, m.auth, m.email, []string{to}, buff.Bytes())
}
......@@ -58,7 +58,9 @@ func (a *api) deactivateOrders() {
now := time.Now()
t := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)
err := a.db.Where("active = ? AND deadline < ?", true, t).
Preload("Transactions.OrderPurchase").
Preload("Member").
Preload("Transactions.OrderPurchase.Product").
Preload("Transactions.Member").
Find(&orders).Error
if err != nil {
log.Println("Error refunding orders:", err)
......@@ -96,6 +98,10 @@ func (a *api) deactivateOrders() {
continue
}
err := a.mail.sendOrder(order.Member.Email, &order)
if err != nil {
log.Println("Error sending order email:", err)
}
log.Println("Refund order", order.Name, total)
}
}
......
......@@ -139,7 +139,7 @@ func TestOrderNoDeactivation(t *testing.T) {
if err != nil {
t.Fatal("Can't initialize the db:", err)
}
a := api{db: db}
a := api{db: db, mail: NewMail("", "", "")}
a.deactivateOrders()
resp = tapi.do("GET", "/order/active", nil, &orders)
......@@ -191,7 +191,7 @@ func TestOrderDeactivation(t *testing.T) {
if err != nil {
t.Fatal("Can't initialize the db:", err)
}
a := api{db: db}
a := api{db: db, mail: NewMail("", "", "")}
a.deactivateOrders()
resp = tapi.do("GET", "/order/active", nil, &orders)
......
......@@ -38,17 +38,21 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
func main() {
var (
dbPath = flag.String("db-path", env.String("./test.db", "DB_PATH"), "Path where the sqlite will be located {DB_PATH}")
addr = flag.String("addr", env.String(":8080", "HTTP_ADDR", "ADDR"), "Address where the http server will bind {HTTP_ADDR}")
signKey = flag.String("signkey", env.String("", "SIGNKEY"), "Sign key for authentication tokens. DO NOT LEAVE UNSET!!! {SIGNKEY}")
assets = flag.String("assets", env.String("./build", "ASSETS_PATH"), "Path to the assets (js, html, ...) {ASSETS_PATH}")
dbPath = flag.String("db-path", env.String("./test.db", "DB_PATH"), "Path where the sqlite will be located {DB_PATH}")
addr = flag.String("addr", env.String(":8080", "HTTP_ADDR", "ADDR"), "Address where the http server will bind {HTTP_ADDR}")
signKey = flag.String("signkey", env.String("", "SIGNKEY"), "Sign key for authentication tokens. DO NOT LEAVE UNSET!!! {SIGNKEY}")
assets = flag.String("assets", env.String("./build", "ASSETS_PATH"), "Path to the assets (js, html, ...) {ASSETS_PATH}")
mailServer = flag.String("mail-server", env.String("", "MAIL_SERVER"), "Address of the smtp server as hotname:port {MAIL_SERVER}")
mailAddr = flag.String("mail-addr", env.String("", "MAIL_ADDR"), "Email address to send the emails from {MAIL_ADDR}")
mailPass = flag.String("mail-pass", env.String("", "MAIL_PASS"), "Password of the email account {MAIL_PASS}")
)
flag.Parse()
log.Println("listening in address:", *addr)
r := mux.NewRouter()
apiRouter := r.PathPrefix("/api/").Subrouter()
err := api.Init(*dbPath, *signKey, apiRouter)
mail := api.NewMail(*mailAddr, *mailPass, *mailServer)
err := api.Init(*dbPath, *signKey, mail, apiRouter)
if err != nil {
log.Panicln("Can't open the database:", err)
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment