Mercurial > gemma
changeset 5334:45805c454436 extented-report
Load users from database who should receive a report.
Generate the report.
TODO: Send the report by mail.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Tue, 01 Jun 2021 01:22:10 +0200 |
parents | 6c0f40676984 |
children | dcd5692a2889 |
files | pkg/imports/report.go |
diffstat | 1 files changed, 108 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/pkg/imports/report.go Tue Jun 01 00:37:03 2021 +0200 +++ b/pkg/imports/report.go Tue Jun 01 01:22:10 2021 +0200 @@ -17,9 +17,18 @@ "context" "database/sql" "errors" + "fmt" + "log" + "os" + "path/filepath" + "regexp" "gemma.intevation.de/gemma/pkg/common" + "gemma.intevation.de/gemma/pkg/config" "gemma.intevation.de/gemma/pkg/models" + "gemma.intevation.de/gemma/pkg/xlsx" + + "github.com/360EntSecGroup-Skylar/excelize/v2" ) type Report struct { @@ -69,6 +78,57 @@ return nil } +func (r *Report) loadTemplate() (*excelize.File, *xlsx.Action, error) { + path := config.ReportPath() + if path == "" { + return nil, nil, errors.New("no report dir configured") + } + + if stat, err := os.Stat(path); err != nil { + if os.IsNotExist(err) { + return nil, nil, fmt.Errorf("report dir '%s' does not exists", path) + } + return nil, nil, err + } else if !stat.Mode().IsDir() { + return nil, nil, fmt.Errorf("report dir '%s' is not a directory", path) + } + + // TODO: Prevent this earlier. + if match, _ := regexp.MatchString(`^[a-zA-Z0-9_]+$`, r.Name); !match { + return nil, nil, errors.New("invalid report name") + } + + xlsxFilename := filepath.Join(path, r.Name+".xlsx") + yamlFilename := filepath.Join(path, r.Name+".yaml") + + for _, check := range []string{xlsxFilename, yamlFilename} { + if _, err := os.Stat(check); err != nil { + if os.IsNotExist(err) { + return nil, nil, fmt.Errorf("'%s' does not exists", check) + } + return nil, nil, err + } + } + + template, err := excelize.OpenFile(xlsxFilename) + if err != nil { + return nil, nil, err + } + + action, err := xlsx.ActionFromFile(yamlFilename) + if err != nil { + return nil, nil, err + } + + return template, action, nil +} + +const selectReportUsersSQL = ` +SELECT username, email_address +FROM users.list_users +WHERE report_reciever +ORDER BY country, username` + func (r *Report) Do( ctx context.Context, importID int64, @@ -76,7 +136,54 @@ feedback Feedback, ) (interface{}, error) { - // TODO: Implement me! + template, action, err := r.loadTemplate() + if err != nil { + return nil, err + } + + tx, err := conn.BeginTx(ctx, &sql.TxOptions{ReadOnly: true}) + if err != nil { + return nil, err + } + defer tx.Rollback() + + type user struct { + name string + email string + } + + var users []user + + if err := func() error { + rows, err := tx.QueryContext(ctx, selectReportUsersSQL) + if err != nil { + return err + } + defer rows.Close() + + for rows.Next() { + var u user + if err := rows.Scan(&u.name, &u.email); err != nil { + return err + } + users = append(users, u) + } + return rows.Err() + }(); err != nil { + return nil, err + } + + if len(users) == 0 { + feedback.Warn("No users found to send reports to.") + return nil, nil + } + + if err := action.Execute(ctx, tx, template); err != nil { + log.Printf("error: %v\n", err) + return nil, fmt.Errorf("Generating report failed: %v", err) + } + + // TODO: Send report via email to users. return nil, nil }