diff --git a/biz/config/config.go b/biz/config/config.go index de84ea7..ea6635b 100644 --- a/biz/config/config.go +++ b/biz/config/config.go @@ -3,15 +3,18 @@ package config import ( "errors" "fmt" + "github.com/spf13/viper" "regexp" "strconv" "strings" "time" ) +var DefaultConfig = &Config{} + type ( Config struct { - Systems []System + Systems []System `json:"System" mapstructure:"System"` } System struct { Name string @@ -23,10 +26,11 @@ type ( Name string Tasks []Task File string + Size int //文件最大行数 } Task struct { - PK string + PK string `mapstructure:"pk"` Sql string Timestamp bool Elt string @@ -34,22 +38,22 @@ type ( } ) -func (c Config) GetSystem(system string) (System, error) { +func (c Config) GetSystem(name string) (System, error) { for _, s := range c.Systems { - if s.Name == system { + if s.Name == name { return s, nil } } - return System{}, errors.New("没有找到相关配置:" + system) + return System{}, errors.New("没有找到相关配置:" + name) } -func (s System) GetJob(job string) (Job, error) { +func (s System) GetJob(name string) (Job, error) { for _, j := range s.Jobs { - if j.Name == job { + if j.Name == name { return j, nil } } - return Job{}, errors.New("没有找到相关配置:" + job) + return Job{}, errors.New("没有找到相关配置:" + name) } func (t Task) GetSql(params map[string]interface{}) string { @@ -94,3 +98,25 @@ func (t Task) getParam(parm interface{}) string { return fmt.Sprint(p) } } + +func LoadConfig(path string) *Config { + var c Config + + viper.AddConfigPath(path) //设置读取的文件路径 + viper.SetConfigName("Config") //设置读取的文件名 + viper.SetConfigType("yaml") //设置文件的类型 + + //尝试进行配置读取 + if err := viper.ReadInConfig(); err != nil { + fmt.Println("请将config.yml.example拷贝为config.yaml") + panic(err) + } + //v := viper.GetViper() + //fmt.Println(v) + if err := viper.Unmarshal(&c); err != nil { + panic(err) + } + + DefaultConfig = &c + return &c +} diff --git a/biz/config/config_test.go b/biz/config/config_test.go new file mode 100644 index 0000000..6a2ac56 --- /dev/null +++ b/biz/config/config_test.go @@ -0,0 +1,25 @@ +package config + +import ( + "github.com/stretchr/testify/assert" + "os" + "testing" +) + +func TestLoadConfig(t *testing.T) { + path, err := os.Getwd() + assert.Nil(t, err) + + path = path + "/../../Config/" + config := LoadConfig(path) + + zltx, err := config.GetSystem("直连天下") + assert.Nil(t, err) + assert.Equal(t, "root:root@tcp(192.168.6.74:3307)/new_sys?charset=utf8mb4&parseTime=True", zltx.Db) + + order, err := zltx.GetJob("上游订单") + assert.Nil(t, err) + assert.Len(t, order.Tasks, 2) + + assert.False(t, order.Tasks[0].Timestamp) +} diff --git a/biz/db/db.go b/biz/db/db.go new file mode 100644 index 0000000..854e679 --- /dev/null +++ b/biz/db/db.go @@ -0,0 +1,99 @@ +package db + +import ( + "database/sql" + "database/sql/driver" + "excel_export/biz/export" + "fmt" + "gorm.io/driver/mysql" + "gorm.io/gorm" + "reflect" +) + +var _ export.DataFetcher = new(Db) + +type Db struct { + db *gorm.DB +} + +func NewDb(str string) (*Db, error) { + db, err := gorm.Open(mysql.Open(str + "")) + if err != nil { + return nil, err + } + //db = db.Debug() + return &Db{ + db: db, + }, nil +} + +func (d *Db) Fetch(s string) (*export.Data, error) { + + rows, err := d.db.Raw(s).Rows() + if err != nil { + return nil, err + } + defer rows.Close() + titles, values, err := getRowStruct(rows) + if err != nil { + return nil, err + } + + var data []interface{} + + for rows.Next() { + rows.Scan(values...) + row := make([]interface{}, len(values)) + for i, value := range values { + + vv := reflect.ValueOf(value) + if vv.Kind() == reflect.Ptr { + //将指针对象转换为值对象 + value = vv.Elem().Interface() + } + + switch vvv := value.(type) { + case driver.Valuer: + row[i], _ = vvv.Value() + case sql.RawBytes: + row[i] = string(vvv) + default: + row[i] = vvv + } + } + + data = append(data, row) + // 业务逻辑... + } + + return &export.Data{ + Title: titles, + Data: data, + }, nil +} + +func getRowStruct(rows *sql.Rows) (title []string, t []interface{}, err error) { + titles, _ := rows.Columns() + + tt, err := rows.ColumnTypes() + if err != nil { + return nil, nil, fmt.Errorf("ColumnTypes: %v", err) + } + + types := make([]reflect.Type, len(tt)) + for i, tp := range tt { + st := tp.ScanType() + if st == nil { + return nil, nil, fmt.Errorf("scantype is null for column %q", tp.Name()) + } + types[i] = st + } + + values := make([]interface{}, len(tt)) + for i := range values { + values[i] = reflect.New(types[i]).Interface() + } + + return titles, values, nil + +} diff --git a/biz/db/db_test.go b/biz/db/db_test.go new file mode 100644 index 0000000..c834a28 --- /dev/null +++ b/biz/db/db_test.go @@ -0,0 +1,24 @@ +package db + +import ( + "fmt" + "github.com/stretchr/testify/assert" + "testing" +) + +const test_db = "root:root@(192.168.6.74:3307)/recharge_trade?charset=utf8mb4&parseTime=true" + +func TestDb_Fetch(t *testing.T) { + db, err := NewDb(test_db) + assert.Nil(t, err) + + sql := "select trade_number as `交易号`,account as `充值号码` from trade limit 10" + ret, err := db.Fetch(sql) + assert.Nil(t, err) + fmt.Printf("%v \n", ret) + item := ret.Data[0].([]interface{}) + for _, i := range item { + fmt.Printf("%v", i) + } + +} diff --git a/biz/export/excel.go b/biz/export/excel.go index c5b93c4..0dc45af 100644 --- a/biz/export/excel.go +++ b/biz/export/excel.go @@ -3,6 +3,7 @@ package export import ( "errors" "github.com/tealeg/xlsx/v3" + "reflect" ) const Sheet_Name = "sheet_1" @@ -57,7 +58,7 @@ func (e *Excel) Open() error { } } else { //需要处理偏移数据 - e.f.SetRow(e.sheet.MaxRow - 1) + e.f.SetRow(e.sheet.MaxRow) } return nil @@ -78,6 +79,7 @@ func (e *Excel) WriteTitle(titles []string) error { if e.titles != nil && e.isNew { e.Write(e.titles) + e.isNew = false } return nil } @@ -87,7 +89,24 @@ func (e *Excel) Write(data interface{}) error { e.reset() } row := e.sheet.AddRow() - row.WriteSlice(data, -1) + + v := reflect.ValueOf(data) + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + if v.Kind() != reflect.Slice { + return errors.New("数据无效,不是切片类型") + } + + switch val := data.(type) { + case []string: + row.WriteSlice(val, -1) + case []interface{}: + for _, i := range data.([]interface{}) { + cell := row.AddCell() + cell.SetValue(i) + } + } return nil } diff --git a/biz/export/excel_exporter.go b/biz/export/excel_exporter.go index e500213..a553adc 100644 --- a/biz/export/excel_exporter.go +++ b/biz/export/excel_exporter.go @@ -1,8 +1,12 @@ package export +import "fmt" + type ExcelExporter struct { mFetcher DataFetcher file FileAdapter + count int + last interface{} } func NewExcelExporter(fetcher DataFetcher, file FileAdapter) DataExporter { @@ -20,15 +24,38 @@ func (ee *ExcelExporter) File(file FileAdapter) { ee.file = file } -func (ee *ExcelExporter) Export(sql string) error { - rows := ee.mFetcher.Fetch(sql) - //fmt.Printf("Excel Exporter.Excel, got %v rows\n", len(rows)) - ee.file.Open() - ee.file.WriteTitle([]string{"字段1", "字段2", "字段3", "字段4", "字段5"}) - for _, v := range rows { - // fmt.Printf(" 行号: %d 值: %s\n", i+1, v) - ee.file.Write(v) +func (ee *ExcelExporter) Export(sql, pk string) error { + data, err := ee.mFetcher.Fetch(sql) + if err != nil { + return fmt.Errorf("数据获取错误:%w", err) } + ee.count = len(data.Data) + //fmt.Printf("Excel Exporter.Excel, got %v data\n", len(data)) + ee.file.Open() + ee.file.WriteTitle(data.Title) + var last interface{} + for _, val := range data.Data { + last = val + ee.file.Write(last) + } + + if row, ok := last.([]interface{}); ok { + ee.last = row[getPkIndex(data.Title, pk)] + } + ee.file.Close() return nil } + +func (ee *ExcelExporter) Last() (int, interface{}) { + return ee.count, ee.last +} + +func getPkIndex(titles []string, pk string) int { + for i, title := range titles { + if title == pk { + return i + } + } + return -1 +} diff --git a/biz/export/export.go b/biz/export/export.go index 40dd197..1e4896a 100644 --- a/biz/export/export.go +++ b/biz/export/export.go @@ -4,10 +4,16 @@ type ( DataExporter interface { Fetcher(fetcher DataFetcher) File(file FileAdapter) - Export(sql string) error + Export(sql, pk string) error + Last() (int, interface{}) + } + + Data struct { + Title []string + Data []interface{} } DataFetcher interface { - Fetch(sql string) []interface{} + Fetch(sql string) (*Data, error) } FileAdapter interface { diff --git a/biz/export/mysql_data_fetcher.go b/biz/export/mysql_data_fetcher.go index 3d7bf98..40ea077 100644 --- a/biz/export/mysql_data_fetcher.go +++ b/biz/export/mysql_data_fetcher.go @@ -8,11 +8,14 @@ type MysqlDataFetcher struct { Config string } -func (mf *MysqlDataFetcher) Fetch(sql string) []interface{} { +func (mf *MysqlDataFetcher) Fetch(sql string) (*Data, error) { rows := make([]interface{}, 0, 6) // 插入6个随机数组成的切片,模拟查询要返回的数据集 rows = append(rows, rand.Perm(5), rand.Perm(5), rand.Perm(5), rand.Perm(5), rand.Perm(5), rand.Perm(5)) - return rows + return &Data{ + Title: []string{"字段1", "字段2", "字段3", "字段4", "字段5"}, + Data: rows, + }, nil } func NewMysqlDataFetcher(configStr string) DataFetcher { diff --git a/cmd/cmd/export.go b/cmd/cmd/export.go new file mode 100644 index 0000000..1b15922 --- /dev/null +++ b/cmd/cmd/export.go @@ -0,0 +1,77 @@ +package cmd + +import ( + "excel_export/biz/config" + "excel_export/biz/db" + "excel_export/biz/export" + "fmt" + "strconv" + "time" +) + +func Export(conf *config.Config, sysName, jobName string, begin, end time.Time, batch int) error { + job, dbStr, err := GetJob(conf, sysName, jobName) + if err != nil { + return err + } + + d, err := db.NewDb(dbStr) + if err != nil { + return err + } + + return JobHandler(job, d, map[string]interface{}{ + "begin": begin, + "end": end, + "last": 0, + }, batch) +} + +func GetJob(conf *config.Config, sys, job string) (config.Job, string, error) { + s, err := conf.GetSystem(sys) + if err != nil { + return config.Job{}, "", err + } + + j, err := s.GetJob(job) + if err != nil { + return config.Job{}, "", err + } + return j, s.Db, nil +} + +func JobHandler(job config.Job, d export.DataFetcher, params map[string]interface{}, batch int) error { + + f := export.NewExcel(job.File, job.Size, map[string]string{ + "begin": params["begin"].(time.Time).Format("20060102"), + "end": params["end"].(time.Time).Format("20060102"), + }) + + for i, task := range job.Tasks { + fmt.Printf("执行导出任务:%d\n", i+1) + if err := TaskExport(d, task, params, f, batch); err != nil { + return err + } + } + return nil +} + +func TaskExport(d export.DataFetcher, t config.Task, params map[string]interface{}, f export.FileAdapter, batch int) error { + //todo 最多分1000个批次进行处理 + for i := 0; i < 1000; i++ { + sql := t.GetSql(params) + + e := export.NewExcelExporter(d, f) + + e.Export(sql+" limit "+strconv.Itoa(batch), t.PK) + + count, last := e.Last() + fmt.Printf("已导出 %d 条数据\n", batch*i+count) + if count < batch { + break + } + + params["last"] = last + } + return nil +} diff --git a/cmd/cmd/order.go b/cmd/cmd/order.go deleted file mode 100644 index ab2f3e2..0000000 --- a/cmd/cmd/order.go +++ /dev/null @@ -1,35 +0,0 @@ -package cmd - -import ( - "excel_export/biz" - "excel_export/data" - "github.com/spf13/cobra" -) - -var OrderCmd = &cobra.Command{ - Use: "order", - Short: "导出订单记录", - Run: orderRun, -} - -func orderRun(cmd *cobra.Command, args []string) { - begin := MustFlagsDateTime(cmd, "begin") - end := MustFlagsDateTime(cmd, "end") - - query, limit, path := GetGlobalFlags(cmd) - - db := data.Conn() - repo := data.NewOrderRepo(db) - historyRepo := data.NewHistoryOrderRepo(db) - - orderBiz := biz.NewOrderBiz(repo, historyRepo, biz.NewExportOpts(query, limit, path)) - - cmd.Println("开始导出文件...") - cobra.CheckErr(orderBiz.Export(begin, end)) - - cmd.Println("导出文件完成") - for _, name := range orderBiz.FileNames() { - cmd.Println(name) - } - -} diff --git a/cmd/cmd/root.go b/cmd/cmd/root.go index 7afec75..39dc804 100644 --- a/cmd/cmd/root.go +++ b/cmd/cmd/root.go @@ -1,8 +1,11 @@ package cmd import ( + "excel_export/biz/config" + "fmt" "github.com/spf13/cobra" - "os" + "strconv" + "time" ) var rootCmd = &cobra.Command{ @@ -10,19 +13,83 @@ var rootCmd = &cobra.Command{ Short: "导出直充系统订单数据", SilenceUsage: true, SilenceErrors: true, + Run: rootRun, } func Execute() { - path, _ := os.Getwd() - rootCmd.PersistentFlags().StringP("path", "p", path, "文件路径") - rootCmd.PersistentFlags().IntP("query", "q", 10000, "单次查询数") - rootCmd.PersistentFlags().IntP("limit", "l", 1000000, "单个文档最大记录数") + rootCmd.Flags().IntP("query", "q", 10000, "单次查询数") - OrderCmd.Flags().StringP("begin", "b", "", "开始时间,如:2006-01-02 15:04:05") - OrderCmd.Flags().StringP("end", "e", "", "结束时间,如:2006-01-02 15:04:05") + rootCmd.Flags().StringP("system", "s", "", "需要导出的系统") + rootCmd.Flags().StringP("job", "j", "", "需要导出的任务") + rootCmd.Flags().StringP("begin", "b", "", "开始时间,如:2006-01-02 15:04:05") + rootCmd.Flags().StringP("end", "e", "", "结束时间,如:2006-01-02 15:04:05") + // rootCmd.AddCommand(ExportCmd) - rootCmd.AddCommand(OrderCmd) cobra.CheckErr(rootCmd.Execute()) } + +func rootRun(cmd *cobra.Command, args []string) { + + fmt.Println(args) + c := config.DefaultConfig + + sName := cmd.Flag("system").Value.String() + if sName == "" { + cmd.Println("支持的系统") + for i, system := range c.Systems { + cmd.Printf("\t %d\t%s\n", i+1, system.Name) + } + return + } + + var sys config.System + sIndex, err := strconv.Atoi(sName) + if err == nil { + sys = c.Systems[sIndex-1] + sName = sys.Name + } else { + sys, err = c.GetSystem(sName) + if err != nil { + CmdError(cmd, "%s", err.Error()) + } + } + + jName := cmd.Flag("job").Value.String() + if jName == "" { + cmd.Println("支持的任务") + for i, job := range sys.Jobs { + cmd.Printf("\t %d\t%s \n", i+1, job.Name) + } + return + } + + var job config.Job + jIndex, err := strconv.Atoi(jName) + if err == nil { + job = sys.Jobs[jIndex-1] + jName = job.Name + } else { + job, err = sys.GetJob(jName) + if err != nil { + CmdError(cmd, "%s", err.Error()) + } + } + + fmt.Printf("[%s]执行【%s】【%s】导出\n", time.Now().Format("2006-01-02 15:04:05"), sName, jName) + + begin := MustFlagsDateTime(cmd, "begin") + end := MustFlagsDateTime(cmd, "end") + + query := cmd.Flag("query").Value.String() + batch, err := strconv.Atoi(query) + if err != nil { + CmdError(cmd, "无效的参数:%s", err.Error()) + } + b := time.Now() + Export(config.DefaultConfig, sName, jName, begin, end, batch) + e := time.Now() + fmt.Println("耗时:" + e.Sub(b).String()) + +} diff --git a/cmd/cmd/uitls.go b/cmd/cmd/uitls.go index db1c44e..0c3d132 100644 --- a/cmd/cmd/uitls.go +++ b/cmd/cmd/uitls.go @@ -35,15 +35,3 @@ func CmdError(cmd *cobra.Command, format string, opts ...interface{}) { fmt.Fprintf(cmd.OutOrStderr(), format, opts...) os.Exit(1) } - -func GetGlobalFlags(cmd *cobra.Command) (int, int, string) { - path, err := cmd.Flags().GetString("path") - cobra.CheckErr(err) - - query, err := cmd.Flags().GetInt("query") - cobra.CheckErr(err) - - limit, err := cmd.Flags().GetInt("limit") - cobra.CheckErr(err) - return query, limit, path -} diff --git a/cmd/main.go b/cmd/main.go index a80b1a0..3ced8c8 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -1,20 +1,26 @@ package main -import "excel_export/cmd/cmd" +import ( + "excel_export/biz/config" + "excel_export/cmd/cmd" + "github.com/tealeg/xlsx/v3" + "os" + "time" +) + +var Config *config.Config func main() { + //设置默认格式 + xlsx.DefaultDateTimeOptions = xlsx.DateTimeOptions{ + Location: time.UTC, + ExcelTimeFormat: "yyyy-m-d h:mm:ss", + } + xlsx.DefaultDateTimeFormat = "" + + path, _ := os.Getwd() + Config = config.LoadConfig(path + "/config") + cmd.Execute() + os.Exit(0) } - -//分块获取数据 - -//获取关联表单数据 - -//组装数据 - -//将数据写入excel中 - -//更具切割参数,计算拆分文件序号 - -//并发读写数据的能力 -//控制内存使用、cpu使用 diff --git a/config/config.yaml b/config/config.yaml index 5e8c693..c4a42d4 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -1,10 +1,11 @@ system: - name: "直连天下" - db: "" + db: "root:lhb767@tcp(120.79.35.82:3307)/new_sys?charset=utf8mb4&parseTime=True" jobs: - name: "卡密订单" tasks: - - sql: >- + - pk: "订单号" + sql: >- SELECT order_number AS `订单号` , reseller_order_number AS `分销商订单号`, @@ -27,10 +28,12 @@ system: timestamp: true elt: "order_card.create_time BETWEEN {begin} AND {end} and order_card.order_number > {last}" order: "order_card.create_time,order_card.order_number" - file: "直连天下-卡密订单-${month}.xlsx" + file: "直连天下-卡密订单-{begin}-{end}.xlsx" + size: 10000 - name: "上游订单" tasks: - - sql: >- + - pk: "流水号" + sql: >- SELECT o.reseller_id as `分销商id`, r.`name` as `分销商名称`, @@ -73,7 +76,8 @@ system: timestamp: false elt: "od.create_time BETWEEN '{begin}' and '{end}' and od.serial_number > {last}" order: "od.create_time,od.serial_number" - - sql: >- + - pk: "流水号" + sql: >- SELECT o.reseller_id as `分销商id`, r.`name` as `分销商名称`, @@ -118,10 +122,12 @@ system: timestamp: false elt: "od.create_time BETWEEN '{begin}' and '{end}' and od.serial_number > {last}" order: "od.create_time,od.serial_number" - file: "直连天下-上游订单-${month}.xlsx" + file: "直连天下-上游订单-{begin}-{end}.xlsx" + size: 10000 - name: "下游订单" tasks: - - sql: >- + - ps: "订单号" + sql: >- SELECT o.order_number as `订单号`, o.reseller_id as `分销商id`, @@ -166,7 +172,8 @@ system: elt: "o.`create_time` >= '{begin}' and o.create_time < '{end}' and o.order_number > {last}" timestamp: false order: "o.create_time,o.order_number" - - sql: >- + - pk: "订单号" + sql: >- SELECT o.order_number as `订单号`, o.reseller_id as `分销商id`, @@ -212,13 +219,18 @@ system: elt: "o.`create_time` >= {begin} and o.create_time < {end} and o.order_number > {last}" timestamp: true order: "o.create_time,o.order_number" - file: "直连天下-下游订单-${month}.xlsx" + file: "直连天下-下游订单-{begin}-{end}.xlsx" + size: 10000 - name: "营销系统" db: "" jobs: - name: "订单信息" tasks: - - sql: "" + - pk: "" + sql: "" elt: "" - file: "营销系统-订单信息-${month}.xlsx" \ No newline at end of file + timestamp: true + order: "" + file: "营销系统-订单信息-{begin}-{end}.xlsx" + size: 10000 \ No newline at end of file diff --git a/data/batch.go b/data/batch.go deleted file mode 100644 index effabcc..0000000 --- a/data/batch.go +++ /dev/null @@ -1,17 +0,0 @@ -package data - -type Batch struct { - BatchId string `gorm:"primaryKey;column:batch_id"` - Customer string - Price float32 - DingTalkSn string - Remark string - Success int - Fail int - ResellerId int - Reseller Reseller `gorm:"foreignkey:id;references:reseller_id"` -} - -func (b Batch) TableName() string { - return "batch_direct" -} diff --git a/data/card.go b/data/card.go deleted file mode 100644 index 2a72c33..0000000 --- a/data/card.go +++ /dev/null @@ -1,63 +0,0 @@ -package data - -import ( - "context" - "gorm.io/gorm" - "time" -) - -type Card struct { - OrderNumber string `gorm:"primaryKey;column:order_number"` - ResellerId int `gorm:"column:reseller_id"` - ResellerOrderNumber string `gorm:"column:reseller_order_number"` - OursProductId int `gorm:"column:ours_product_id"` - Price float32 `gorm:"column:price"` - Quantity int `gorm:"column:quantity"` - Amount float32 `gorm:"column:amount"` - PayStatus int `gorm:"column:pay_status"` - Status int `gorm:"column:status"` - Profit float32 `gorm:"column:profit"` - NotifyTime int64 `gorm:"column:notify_time"` - CreateIp int64 `gorm:"column:create_ip"` - CreateTime int64 `gorm:"column:create_time"` - CardCode string `gorm:"column:card_code"` - FinishTime time.Time `gorm:"column:finish_time"` - Message string `gorm:"column:message"` - Mobile string `gorm:"column:mobile"` - OurProduct OurProduct `gorm:"foreignkey:id;references:ours_product_id"` - Reseller Reseller `gorm:"foreignkey:id;references:reseller_id"` -} - -func (o Card) TableName() string { - return "order_card" -} - -type CardRepo struct { - db *gorm.DB -} - -func NewCardRepo(db *gorm.DB) *CardRepo { - return &CardRepo{ - db: db, - } -} - -func (repo CardRepo) List(ctx context.Context, begin, end time.Time, limit int, last string) ([]Card, error) { - var orders []Card - db := repo.db.WithContext(ctx). - Preload("OurProduct"). - Preload("Reseller"). - Where("create_time BETWEEN ? AND ?", begin.Unix(), end.Unix()) - if last != "" { - db.Where("order_number > ?", last) - } - result := db.Order("create_time,order_number"). - Limit(limit). - Find(&orders) - - if result.Error != nil { - return nil, result.Error - } - - return orders, nil -} diff --git a/data/card_test.go b/data/card_test.go deleted file mode 100644 index 8bb2be2..0000000 --- a/data/card_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package data - -import ( - "context" - "fmt" - "github.com/stretchr/testify/assert" - "testing" - "time" -) - -func cardRepo() *CardRepo { - db := Conn() - return NewCardRepo(db) -} - -func TestCardRepo_List(t *testing.T) { - repo := cardRepo() - begin := time.Date(2018, 10, 1, 0, 0, 0, 0, time.Local) - end := time.Date(2023, 12, 1, 0, 0, 0, 0, time.Local) - cards, err := repo.List(context.Background(), begin, end, 10, "123") - assert.Nil(t, err) - fmt.Printf("%+v\n", cards) - -} diff --git a/data/common.go b/data/common.go deleted file mode 100644 index 642b1cd..0000000 --- a/data/common.go +++ /dev/null @@ -1,40 +0,0 @@ -package data - -type OurProduct struct { - Id int64 `gorm:"column:id"` - Name string `gorm:"column:name"` -} - -func (o OurProduct) TableName() string { - return "ours_product" -} - -type Platform struct { - Id int64 - Name string -} - -func (p Platform) TableName() string { - return "platform" -} - -type PlatformProduct struct { - Id int64 - PlatformId int64 - Name string - Code string - Platform Platform `gorm:"foreignkey:id;references:platform_id"` -} - -func (p PlatformProduct) TableName() string { - return "platform_product" -} - -type Reseller struct { - Id int64 `gorm:"primaryKey;column:id"` - Name string -} - -func (o Reseller) TableName() string { - return "reseller" -} diff --git a/data/conn.go b/data/conn.go deleted file mode 100644 index 5d21486..0000000 --- a/data/conn.go +++ /dev/null @@ -1,14 +0,0 @@ -package data - -import ( - "gorm.io/driver/mysql" - "gorm.io/gorm" -) - -func Conn() *gorm.DB { - conn, err := gorm.Open(mysql.Open("root:root@tcp(192.168.6.74:3307)/new_sys?charset=utf8mb4&parseTime=True")) - if err != nil { - panic("数据库连接失败") - } - return conn //.Debug() -} diff --git a/data/direct.go b/data/direct.go deleted file mode 100644 index 6033c55..0000000 --- a/data/direct.go +++ /dev/null @@ -1,87 +0,0 @@ -package data - -import ( - "context" - "gorm.io/gorm" - "time" -) - -type Direct struct { - SerialNumber string `gorm:"primaryKey;column:serial_number"` - OrderOrderNumber string `gorm:"column:order_order_number"` - TerminalAccount string `gorm:"column:terminal_account"` - OursProductId int `gorm:"column:ours_product_id"` - Status int `gorm:"column:status"` - TradePrice float32 `gorm:"column:trade_price"` - PlatformProductId int `gorm:"column:platform_product_id"` - PlatformPrice float32 `gorm:"column:platform_price"` - CreateTime time.Time `gorm:"column:create_time"` - ExecuteTime time.Time `gorm:"column:execute_time"` - Identifier int `gorm:"column:identifier"` - Version int `gorm:"column:version"` - Type int `gorm:"column:type"` - Position int `gorm:"column:position"` - Order Order `gorm:"foreignkey:order_number;references:order_order_number"` - OrderItem OrderItem `gorm:"foreignkey:order_order_number;references:order_order_number"` - PlatformProduct PlatformProduct `gorm:"foreignkey:id;references:platform_product_id"` - Batch Batch `gorm:"foreignkey:batch_id;references:order_order_number"` -} - -func (d Direct) TableName() string { - return "order_direct" -} - -type DirectRepo struct { - db *gorm.DB -} - -func NewDirectRepo(db *gorm.DB) *DirectRepo { - return &DirectRepo{ - db: db, - } -} - -func (repo DirectRepo) List(ctx context.Context, begin, end time.Time, limit int, last string) ([]Direct, error) { - var directs []Direct - db := repo.db.WithContext(ctx). - Preload("Order.Remark"). - Preload("Order.Reseller"). - Preload("OrderItem"). - Preload("PlatformProduct"). - Preload("PlatformProduct.Platform"). - Where("create_time BETWEEN ? AND ?", begin, end) - if last != "" { - db.Where("serial_number > ?", last) - } - result := db.Order("create_time,serial_number"). - Limit(limit). - Find(&directs) - - if result.Error != nil { - return nil, result.Error - } - - return directs, nil -} - -func (repo DirectRepo) BatchList(ctx context.Context, begin, end time.Time, limit int, last string) ([]Direct, error) { - var directs []Direct - db := repo.db.WithContext(ctx). - InnerJoins("Batch"). - Preload("Batch.Reseller"). - Preload("PlatformProduct"). - Preload("PlatformProduct.Platform"). - Where("order_direct.create_time BETWEEN ? AND ?", begin, end) - if last != "" { - db.Where("order_direct.serial_number > ?", last) - } - result := db.Order("order_direct.create_time,order_direct.serial_number"). - Limit(limit). - Find(&directs) - - if result.Error != nil { - return nil, result.Error - } - - return directs, nil -} diff --git a/data/direct_test.go b/data/direct_test.go deleted file mode 100644 index 00f3626..0000000 --- a/data/direct_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package data - -import ( - "context" - "fmt" - "github.com/stretchr/testify/assert" - "testing" - "time" -) - -func directRepo() *DirectRepo { - db := Conn() - return NewDirectRepo(db) -} - -func TestDirectRepo_List(t *testing.T) { - repo := directRepo() - begin := time.Date(2022, 10, 1, 0, 0, 0, 0, time.Local) - end := time.Date(2022, 12, 1, 0, 0, 0, 0, time.Local) - directs, err := repo.List(context.Background(), begin, end, 10, "123") - assert.Nil(t, err) - fmt.Printf("%+v\n", directs) - -} - -func TestDirectRepo_BatchList(t *testing.T) { - repo := directRepo() - begin := time.Date(2022, 10, 1, 0, 0, 0, 0, time.Local) - end := time.Date(2022, 12, 1, 0, 0, 0, 0, time.Local) - directs, err := repo.BatchList(context.Background(), begin, end, 10, "123") - assert.Nil(t, err) - fmt.Printf("%+v\n", directs) -} diff --git a/data/history_direct.go b/data/history_direct.go deleted file mode 100644 index 9a83e1e..0000000 --- a/data/history_direct.go +++ /dev/null @@ -1,87 +0,0 @@ -package data - -import ( - "context" - "gorm.io/gorm" - "time" -) - -type HistoryDirect struct { - SerialNumber string `gorm:"primaryKey;column:serial_number"` - OrderOrderNumber string `gorm:"column:order_order_number"` - TerminalAccount string `gorm:"column:terminal_account"` - OursProductId int `gorm:"column:ours_product_id"` - Status int `gorm:"column:status"` - TradePrice float32 `gorm:"column:trade_price"` - PlatformProductId int `gorm:"column:platform_product_id"` - PlatformPrice float32 `gorm:"column:platform_price"` - CreateTime time.Time `gorm:"column:create_time"` - ExecuteTime time.Time `gorm:"column:execute_time"` - Identifier int `gorm:"column:identifier"` - Version int `gorm:"column:version"` - Type int `gorm:"column:type"` - Position int `gorm:"column:position"` - Order HistoryOrder `gorm:"foreignkey:order_number;references:order_order_number"` - OrderItem HistoryOrderItem `gorm:"foreignkey:order_order_number;references:order_order_number"` - PlatformProduct PlatformProduct `gorm:"foreignkey:id;references:platform_product_id"` - Batch Batch `gorm:"foreignkey:batch_id;references:order_order_number"` -} - -func (d HistoryDirect) TableName() string { - return "history_order_direct" -} - -type HistoryDirectRepo struct { - db *gorm.DB -} - -func NewHistoryDirectRepo(db *gorm.DB) *HistoryDirectRepo { - return &HistoryDirectRepo{ - db: db, - } -} - -func (repo HistoryDirectRepo) List(ctx context.Context, begin, end time.Time, limit int, last string) ([]HistoryDirect, error) { - var directs []HistoryDirect - db := repo.db.WithContext(ctx). - Preload("Order.Remark"). - Preload("Order.Reseller"). - Preload("OrderItem"). - Preload("PlatformProduct"). - Preload("PlatformProduct.Platform"). - Where("create_time BETWEEN ? AND ?", begin, end) - if last != "" { - db.Where("serial_number > ?", last) - } - result := db.Order("create_time,serial_number"). - Limit(limit). - Find(&directs) - - if result.Error != nil { - return nil, result.Error - } - - return directs, nil -} - -func (repo HistoryDirectRepo) BatchList(ctx context.Context, begin, end time.Time, limit int, last string) ([]HistoryDirect, error) { - var directs []HistoryDirect - db := repo.db.WithContext(ctx). - InnerJoins("Batch"). - Preload("Batch.Reseller"). - Preload("PlatformProduct"). - Preload("PlatformProduct.Platform"). - Where("history_order_direct.create_time BETWEEN ? AND ?", begin, end) - if last != "" { - db.Where("history_order_direct.serial_number > ?", last) - } - result := db.Order("history_order_direct.create_time,history_order_direct.serial_number"). - Limit(limit). - Find(&directs) - - if result.Error != nil { - return nil, result.Error - } - - return directs, nil -} diff --git a/data/history_order.go b/data/history_order.go deleted file mode 100644 index 7180462..0000000 --- a/data/history_order.go +++ /dev/null @@ -1,77 +0,0 @@ -package data - -import ( - "context" - "gorm.io/gorm" - "time" -) - -type HistoryOrderItem struct { - OrderNumber string `gorm:"primaryKey;column:order_order_number"` - OursProductId int - OursProductTitle string -} - -func (o HistoryOrderItem) TableName() string { - return "history_order_item" -} - -type HistoryOrderRemark struct { - OrderNumber string `gorm:"primaryKey;column:order_number"` - Remark string -} - -func (o HistoryOrderRemark) TableName() string { - return "history_order_remark" -} - -type HistoryOrder struct { - OrderNumber string `gorm:"primaryKey;column:order_number"` - ResellerId int64 - ResellerOrderNumber string - Amount float32 - Account string - Quantity int - Status int - PayStatus int - CreateTime time.Time - FinishTime time.Time - Item HistoryOrderItem `gorm:"foreignkey:order_order_number;references:order_number"` - Remark HistoryOrderRemark `gorm:"foreignkey:order_number;references:order_number"` - Reseller Reseller `gorm:"foreignkey:id;references:reseller_id"` -} - -func (o HistoryOrder) TableName() string { - return "history_order" -} - -type HistoryOrderRepo struct { - db *gorm.DB -} - -func NewHistoryOrderRepo(db *gorm.DB) *HistoryOrderRepo { - return &HistoryOrderRepo{ - db: db, - } -} - -func (repo HistoryOrderRepo) List(ctx context.Context, begin, end time.Time, limit int, last string) ([]HistoryOrder, error) { - var orders []HistoryOrder - db := repo.db.WithContext(ctx). - Preload("Reseller"). - Preload("Item"). - Preload("Remark"). - Where("create_time BETWEEN ? AND ?", begin, end) - if last != "" { - db.Where("order_number > ?", last) - } - result := db.Order("create_time,order_number"). - Limit(limit). - Find(&orders) - - if result.Error != nil { - return nil, result.Error - } - - return orders, nil -} diff --git a/data/order.go b/data/order.go deleted file mode 100644 index 38f7a33..0000000 --- a/data/order.go +++ /dev/null @@ -1,77 +0,0 @@ -package data - -import ( - "context" - "gorm.io/gorm" - "time" -) - -type OrderItem struct { - OrderNumber string `gorm:"primaryKey;column:order_order_number"` - OursProductId int - OursProductTitle string -} - -func (o OrderItem) TableName() string { - return "order_item" -} - -type OrderRemark struct { - OrderNumber string `gorm:"primaryKey;column:order_number"` - Remark string -} - -func (o OrderRemark) TableName() string { - return "order_remark" -} - -type Order struct { - OrderNumber string `gorm:"primaryKey;column:order_number"` - ResellerId int64 - ResellerOrderNumber string - Amount float32 - Account string - Quantity int - Status int - PayStatus int - CreateTime int64 - FinishTime int64 - Item OrderItem `gorm:"foreignkey:order_order_number;references:order_number"` - Remark OrderRemark `gorm:"foreignkey:order_number;references:order_number"` - Reseller Reseller `gorm:"foreignkey:id;references:reseller_id"` -} - -func (o Order) TableName() string { - return "order" -} - -type OrderRepo struct { - db *gorm.DB -} - -func NewOrderRepo(db *gorm.DB) *OrderRepo { - return &OrderRepo{ - db: db, - } -} - -func (repo OrderRepo) List(ctx context.Context, begin, end time.Time, limit int, last string) ([]Order, error) { - var orders []Order - db := repo.db.WithContext(ctx). - Preload("Reseller"). - Preload("Item"). - Preload("Remark"). - Where("create_time BETWEEN ? AND ?", begin.Unix(), end.Unix()) - if last != "" { - db.Where("order_number > ?", last) - } - result := db.Order("create_time,order_number"). - Limit(limit). - Find(&orders) - - if result.Error != nil { - return nil, result.Error - } - - return orders, nil -} diff --git a/data/order_test.go b/data/order_test.go deleted file mode 100644 index 151f92b..0000000 --- a/data/order_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package data - -import ( - "context" - "fmt" - "testing" - "time" -) - -func orderRepo() *OrderRepo { - db := Conn() - return NewOrderRepo(db) -} -func TestOrderRepo_List(t *testing.T) { - repo := orderRepo() - begin := time.Date(2022, 10, 1, 0, 0, 0, 0, time.Local) - end := time.Date(2022, 12, 1, 0, 0, 0, 0, time.Local) - orders, err := repo.List(context.Background(), begin, end, 10, "123") - fmt.Println(err) - fmt.Printf("%+v\n", orders) -} diff --git a/go.mod b/go.mod index eda2e53..7ab592b 100644 --- a/go.mod +++ b/go.mod @@ -14,27 +14,35 @@ require ( github.com/stretchr/testify v1.8.1 ) -require github.com/smartystreets/goconvey v1.7.2 +require github.com/spf13/viper v1.15.0 require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/frankban/quicktest v1.11.2 // indirect + github.com/frankban/quicktest v1.14.3 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/google/btree v1.0.0 // indirect - github.com/google/go-cmp v0.5.2 // indirect - github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - github.com/jtolds/gls v4.20.0+incompatible // indirect - github.com/kr/pretty v0.2.1 // indirect - github.com/kr/text v0.1.0 // indirect + github.com/kr/pretty v0.3.0 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/fastuuid v1.2.0 // indirect + github.com/rogpeppe/go-internal v1.6.1 // indirect github.com/shabbyrobe/xmlwriter v0.0.0-20200208144257-9fca06d00ffa // indirect - github.com/smartystreets/assertions v1.2.0 // indirect - golang.org/x/text v0.3.3 // indirect - golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect + github.com/spf13/afero v1.9.3 // indirect + github.com/spf13/cast v1.5.0 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/subosito/gotenv v1.4.2 // indirect + golang.org/x/sys v0.3.0 // indirect + golang.org/x/text v0.5.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect )