完成业务流转

This commit is contained in:
Mr.Li 2023-04-06 20:06:44 +08:00
parent fabed6916c
commit 69b5ee0814
26 changed files with 464 additions and 652 deletions

View File

@ -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
}

25
biz/config/config_test.go Normal file
View File

@ -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)
}

99
biz/db/db.go Normal file
View File

@ -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
}

24
biz/db/db_test.go Normal file
View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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 {

View File

@ -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 {

77
cmd/cmd/export.go Normal file
View File

@ -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
}

View File

@ -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)
}
}

View File

@ -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())
}

View File

@ -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
}

View File

@ -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使用

View File

@ -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"
timestamp: true
order: ""
file: "营销系统-订单信息-{begin}-{end}.xlsx"
size: 10000

View File

@ -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"
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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"
}

View File

@ -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()
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}

28
go.mod
View File

@ -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
)