add data export to cli

This commit is contained in:
MaysWind
2021-03-21 20:00:17 +08:00
parent 1a8d228aac
commit 83d65d2e57
3 changed files with 138 additions and 1 deletions
+70
View File
@@ -1,10 +1,13 @@
package cmd package cmd
import ( import (
"os"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
clis "github.com/mayswind/lab/pkg/cli" clis "github.com/mayswind/lab/pkg/cli"
"github.com/mayswind/lab/pkg/log" "github.com/mayswind/lab/pkg/log"
"github.com/mayswind/lab/pkg/utils"
) )
// UserData represents the data command // UserData represents the data command
@@ -24,6 +27,23 @@ var UserData = &cli.Command{
}, },
}, },
}, },
{
Name: "export",
Usage: "Export user all transactions to csv file",
Action: exportUserTransaction,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "username",
Aliases: []string{"n"},
Usage: "Specific user name",
},
&cli.StringFlag{
Name: "file",
Aliases: []string{"f"},
Usage: "Specific exported file path (e.g. transaction.csv)",
},
},
},
}, },
} }
@@ -55,3 +75,53 @@ func checkUserTransactionAndAccount(c *cli.Context) error {
return nil return nil
} }
func exportUserTransaction(c *cli.Context) error {
_, err := initializeSystem(c)
if err != nil {
return err
}
userName := c.String("username")
uid, err := clis.UserData.GetUserIdByUsername(c, userName)
if err != nil {
log.BootErrorf("[user_data.exportUserTransaction] error occurs when getting user id by user name")
return err
}
filePath := c.String("file")
if filePath == "" {
log.BootErrorf("[user_data.exportUserTransaction] export file path is not specified")
return os.ErrNotExist
}
fileExists, err := utils.IsExists(filePath)
if fileExists {
log.BootErrorf("[user_data.exportUserTransaction] specified file path already exists")
return os.ErrExist
}
log.BootInfof("[user_data.exportUserTransaction] starting exporting user \"%s\" data", userName)
content, err := clis.UserData.ExportTransaction(c, uid)
if err != nil {
log.BootErrorf("[user_data.exportUserTransaction] error occurs when exporting user data")
return err
}
err = utils.WriteFile(filePath, content)
if err != nil {
log.BootErrorf("[user_data.exportUserTransaction] failed to write to %s", filePath)
return err
}
log.BootInfof("[user_data.exportUserTransaction] user transactions have been exported to %s", filePath)
return nil
}
+30
View File
@@ -4,15 +4,18 @@ import (
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"github.com/mayswind/lab/pkg/errs" "github.com/mayswind/lab/pkg/errs"
"github.com/mayswind/lab/pkg/exporters"
"github.com/mayswind/lab/pkg/log" "github.com/mayswind/lab/pkg/log"
"github.com/mayswind/lab/pkg/models" "github.com/mayswind/lab/pkg/models"
"github.com/mayswind/lab/pkg/services" "github.com/mayswind/lab/pkg/services"
) )
const pageCountForGettingTransactions = 1000 const pageCountForGettingTransactions = 1000
const pageCountForDataExport = 1000
// UserDataCli represents user data cli // UserDataCli represents user data cli
type UserDataCli struct { type UserDataCli struct {
csvExporter *exporters.CSVFileExporter
accounts *services.AccountService accounts *services.AccountService
transactions *services.TransactionService transactions *services.TransactionService
categories *services.TransactionCategoryService categories *services.TransactionCategoryService
@@ -23,6 +26,7 @@ type UserDataCli struct {
// Initialize an user data cli singleton instance // Initialize an user data cli singleton instance
var ( var (
UserData = &UserDataCli{ UserData = &UserDataCli{
csvExporter: &exporters.CSVFileExporter{},
accounts: services.Accounts, accounts: services.Accounts,
transactions: services.Transactions, transactions: services.Transactions,
users: services.Users, users: services.Users,
@@ -139,6 +143,32 @@ func (a *UserDataCli) CheckTransactionAndAccount(c *cli.Context, uid int64) (boo
return true, nil return true, nil
} }
// ExportTransaction returns csv file content according user all transactions
func (a *UserDataCli) ExportTransaction(c *cli.Context, uid int64) ([]byte, error) {
accountMap, categoryMap, tagMap, tagIndexs, err := a.getUserEssentialData(uid)
if err != nil {
log.BootErrorf("[user_data.ExportTransaction] failed to get essential data for user \"uid:%d\", because %s", uid, err.Error())
return nil, err
}
allTransactions, err := a.transactions.GetAllTransactions(uid, pageCountForDataExport, true)
if err != nil {
log.BootErrorf("[user_data.ExportTransaction] failed to all transactions for user \"uid:%d\", because %s", uid, err.Error())
return nil, err
}
result, err := a.csvExporter.GetOutputContent(uid, allTransactions, accountMap, categoryMap, tagMap, tagIndexs)
if err != nil {
log.BootErrorf("[user_data.ExportTransaction] failed to get csv format exported data for \"uid:%d\", because %s", uid, err.Error())
return nil, err
}
return result, nil
}
// GetUserIdByUsername returns user id by user name // GetUserIdByUsername returns user id by user name
func (a *UserDataCli) GetUserIdByUsername(c *cli.Context, username string) (int64, error) { func (a *UserDataCli) GetUserIdByUsername(c *cli.Context, username string) (int64, error) {
if username == "" { if username == "" {
+38 -1
View File
@@ -1,6 +1,43 @@
package utils package utils
import "io" import (
"io"
"os"
)
// IsExists returns whether specified file or directory path exits
func IsExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
// WriteFile would write file according to specified content
func WriteFile(path string, data []byte) error {
file, err := os.Create(path)
if err != nil {
return err
}
defer file.Close()
n, err := file.Write(data)
if err == nil && n < len(data) {
return io.ErrShortWrite
}
return err
}
// IdentReader returns the original io reader // IdentReader returns the original io reader
func IdentReader(encoding string, input io.Reader) (io.Reader, error) { func IdentReader(encoding string, input io.Reader) (io.Reader, error) {