diff --git a/api/api.go b/api/api.go index a9f50697b2a71ea718597aba099a4c700ba1fdfd..b53a1ae74271850b955468bad734677580357be0 100644 --- a/api/api.go +++ b/api/api.go @@ -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) diff --git a/api/api_test.go b/api/api_test.go index f2c6403626440793815edee56f1e057149706777..63b4cd177994d14a6f9add779cf23ac1e0f81bc7 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -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) } diff --git a/api/mail.go b/api/mail.go new file mode 100644 index 0000000000000000000000000000000000000000..a4924d1585f049c09d9cf96451e0245b402a9d35 --- /dev/null +++ b/api/mail.go @@ -0,0 +1,88 @@ +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()) +} diff --git a/api/order.go b/api/order.go index 11e68eb93cecc3faa9d2cec3acee5394d952c8cf..3ab98dea4bf4bd08bda77e172b99f5e9cb16401b 100644 --- a/api/order.go +++ b/api/order.go @@ -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) } } diff --git a/api/order_test.go b/api/order_test.go index a73261c89bbec5388f0248c6bbe783be177765fc..e3a4ee0807357eb2c0f2dfff6f2344f2f847f8e1 100644 --- a/api/order_test.go +++ b/api/order_test.go @@ -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) diff --git a/main.go b/main.go index 6b10f959279285d0be1dd44afeb3bc5b5264e652..96cc90f6b49add12706cee5d720881d5d2c34bb3 100644 --- a/main.go +++ b/main.go @@ -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) }