refactor(export): 调整导出数据逻辑

This commit is contained in:
Mr.Li 2023-01-31 18:29:45 +08:00
parent 021fcf6cb6
commit 485e8cc944
30 changed files with 1466 additions and 50 deletions

32
biz/BaseExportBiz.go Normal file
View File

@ -0,0 +1,32 @@
package biz
import (
"fmt"
"time"
)
type baseExportBiz struct {
fileSize int
opts *ExportOpts
fileName string
}
func (e *baseExportBiz) FileSize() int {
return e.fileSize
}
func (e *baseExportBiz) FileName() string {
return e.fileName
}
func (e *baseExportBiz) FileNames() []string {
name := make([]string, e.fileSize+1)
for i := 0; i <= e.fileSize; i++ {
name[i] = fmt.Sprintf(e.fileName, i)
}
return name
}
func (e *baseExportBiz) setFileArg(begin time.Time) {
e.fileName = getFielName(e.opts.Path, e.opts.Tag, begin)
}

153
biz/batch.go Normal file
View File

@ -0,0 +1,153 @@
package biz
import (
"context"
"excel_export/data"
"excel_export/export"
"fmt"
"time"
)
func NewBatchBiz(repo *data.DirectRepo, historyRepo *data.HistoryDirectRepo, opts *ExportOpts) *BatchBiz {
biz := &BatchBiz{
repo: repo,
historyRepo: historyRepo,
}
biz.opts = DefaultOpts
if opts != nil {
biz.opts = opts
}
biz.opts.Tag = "batch"
return biz
}
type BatchBiz struct {
repo *data.DirectRepo
historyRepo *data.HistoryDirectRepo
baseExportBiz
}
func (e *BatchBiz) Export(begin, end time.Time) error {
e.setFileArg(begin)
file := export.NewExport(e.fileName, e.opts.ExcelMaxRow)
if err := file.Open(); err != nil {
return err
}
if err := file.Title(export.Batchs{}.Title()); err != nil {
return err
}
//导出历史订单数据
if err := e.exportHistoryData(file, begin, end); err != nil {
return err
}
//导出最近7天数据
if err := e.exportData(file, begin, end); err != nil {
return err
}
e.fileSize = file.Index()
return nil
}
func (e *BatchBiz) exportHistoryData(export *export.Export, begin, end time.Time) error {
var last string
for true {
//导出最近7天数据
data, err := e.historyRepo.BatchList(context.Background(), begin, end, e.opts.QueryLimit, last)
if err != nil {
return fmt.Errorf("获取导出数据错误:%w", err)
}
if err := export.Export(e.HistoryTransforms(data)); err != nil {
return err
}
if len(data) < e.opts.QueryLimit {
return nil
}
last = data[len(data)-1].SerialNumber
}
return nil
}
func (e *BatchBiz) exportData(export *export.Export, begin, end time.Time) error {
var last string
for true {
//导出最近7天数据
data, err := e.repo.BatchList(context.Background(), begin, end, e.opts.QueryLimit, last)
if err != nil {
return fmt.Errorf("获取导出数据错误:%w", err)
}
if err := export.Export(e.Transforms(data)); err != nil {
return err
}
if len(data) < e.opts.QueryLimit {
return nil
}
last = data[len(data)-1].SerialNumber
}
return nil
}
func (e BatchBiz) Transforms(data []data.Direct) export.Batchs {
result := make(export.Batchs, len(data))
for i, val := range data {
result[i] = e.Transform(val)
}
return result
}
func (e BatchBiz) Transform(data data.Direct) *export.Batch {
return &export.Batch{
ResellerId: data.Batch.ResellerId,
ResellerName: data.Batch.Reseller.Name,
OursProductId: data.OursProductId,
OursProductTitle: data.OrderItem.OursProductTitle,
PlatformName: data.PlatformProduct.Platform.Name,
PlatformProductCode: data.PlatformProduct.Code,
PlatformProductName: data.PlatformProduct.Name,
Status: data.Status,
OrderOrderNumber: data.OrderOrderNumber,
SerialNumber: data.SerialNumber,
TerminalAccount: data.TerminalAccount,
TradePrice: data.TradePrice,
PlatformPrice: data.PlatformPrice,
CreateTime: data.CreateTime.Format("2006-01-02 15:04:05"),
ExecuteTime: data.ExecuteTime.Format("2006-01-02 15:04:05"),
Remark: data.Batch.Remark,
}
}
func (e BatchBiz) HistoryTransforms(data []data.HistoryDirect) export.Batchs {
result := make(export.Batchs, len(data))
for i, val := range data {
result[i] = e.HistoryTransform(val)
}
return result
}
func (e BatchBiz) HistoryTransform(data data.HistoryDirect) *export.Batch {
return &export.Batch{
ResellerId: data.Batch.ResellerId,
ResellerName: data.Batch.Reseller.Name,
OursProductId: data.OursProductId,
OursProductTitle: data.OrderItem.OursProductTitle,
PlatformName: data.PlatformProduct.Platform.Name,
PlatformProductCode: data.PlatformProduct.Code,
PlatformProductName: data.PlatformProduct.Name,
Status: data.Status,
OrderOrderNumber: data.OrderOrderNumber,
SerialNumber: data.SerialNumber,
TerminalAccount: data.TerminalAccount,
TradePrice: data.TradePrice,
PlatformPrice: data.PlatformPrice,
CreateTime: data.CreateTime.Format("2006-01-02 15:04:05"),
ExecuteTime: data.ExecuteTime.Format("2006-01-02 15:04:05"),
Remark: data.Batch.Remark,
}
}

36
biz/batch_test.go Normal file
View File

@ -0,0 +1,36 @@
package biz
import (
"excel_export/data"
"fmt"
"github.com/stretchr/testify/assert"
"os"
"testing"
"time"
)
func batchBiz() *BatchBiz {
db := data.Conn()
repo := data.NewDirectRepo(db)
historyRepo := data.NewHistoryDirectRepo(db)
return NewBatchBiz(repo, historyRepo, nil)
}
func TestBatchBiz_Export(t *testing.T) {
biz := batchBiz()
begin := time.Date(2021, 10, 1, 0, 0, 0, 0, time.Local)
end := time.Date(2022, 12, 1, 0, 0, 0, 0, time.Local)
err := biz.Export(begin, end)
assert.Nil(t, err)
for i := 0; i <= biz.FileSize(); i++ {
fileName := fmt.Sprintf(biz.FileName(), i)
assert.FileExists(t, fileName)
//清理文件
os.Remove(fileName)
}
}

90
biz/card.go Normal file
View File

@ -0,0 +1,90 @@
package biz
import (
"context"
"excel_export/data"
"excel_export/export"
"fmt"
"time"
)
func NewCardBiz(repo *data.CardRepo, opts *ExportOpts) *CardBiz {
biz := &CardBiz{
repo: repo,
}
if opts == nil {
opts = DefaultOpts
}
opts.Tag = "card"
biz.opts = opts
return biz
}
type CardBiz struct {
repo *data.CardRepo
baseExportBiz
}
func (e *CardBiz) Export(begin, end time.Time) error {
e.setFileArg(begin)
file := export.NewExport(e.fileName, e.opts.ExcelMaxRow)
if err := file.Open(); err != nil {
return err
}
if err := file.Title(export.Cards{}.Title()); err != nil {
return err
}
if err := e.exportData(file, begin, end); err != nil {
return err
}
e.fileSize = file.Index()
return nil
}
func (e *CardBiz) exportData(export *export.Export, begin, end time.Time) error {
var last string
for true {
//导出最近7天数据
data, err := e.repo.List(context.Background(), begin, end, e.opts.QueryLimit, last)
if err != nil {
return fmt.Errorf("获取导出数据错误:%w", err)
}
if err := export.Export(e.Transforms(data)); err != nil {
return err
}
if len(data) < e.opts.QueryLimit {
return nil
}
last = data[len(data)-1].OrderNumber
}
return nil
}
func (e CardBiz) Transforms(data []data.Card) export.Cards {
result := make(export.Cards, len(data))
for i, val := range data {
result[i] = e.Transform(val)
}
return result
}
func (e CardBiz) Transform(data data.Card) *export.Card {
return &export.Card{
OrderNumber: data.OrderNumber,
ResellerOrderNumber: data.ResellerOrderNumber,
Amount: data.Amount,
Quantity: data.Quantity,
Status: data.Status,
ResellerId: data.ResellerId,
ResellerName: data.Reseller.Name,
OursProductId: data.OursProductId,
OursProductTitle: data.OurProduct.Name,
CreateTime: time.Unix(data.CreateTime, 0).Format("2006-01-02 15:04:05"),
}
}

35
biz/card_test.go Normal file
View File

@ -0,0 +1,35 @@
package biz
import (
"excel_export/data"
"fmt"
"github.com/stretchr/testify/assert"
"os"
"testing"
"time"
)
func cardBiz() *CardBiz {
db := data.Conn()
repo := data.NewCardRepo(db)
return NewCardBiz(repo, nil)
}
func TestCardBiz_Export(t *testing.T) {
biz := cardBiz()
begin := time.Date(2012, 10, 1, 0, 0, 0, 0, time.Local)
end := time.Date(2022, 12, 1, 0, 0, 0, 0, time.Local)
err := biz.Export(begin, end)
assert.Nil(t, err)
for i := 0; i <= biz.FileSize(); i++ {
fileName := fmt.Sprintf(biz.FileName(), i)
assert.FileExists(t, fileName)
//清理文件
os.Remove(fileName)
}
}

41
biz/common.go Normal file
View File

@ -0,0 +1,41 @@
package biz
import (
"fmt"
"os"
"time"
)
const (
QueryLImit = 10
ExcelMaxRow = 10
)
func getFielName(path, filename string, time time.Time) string {
if path == "" {
path, _ = os.Getwd()
}
date := time.Format("20060102")
return fmt.Sprintf("%s/%s_%s_%%d.xlsx", path, filename, date)
}
type ExportOpts struct {
QueryLimit int
ExcelMaxRow int
Path string
Tag string
}
var DefaultOpts *ExportOpts = &ExportOpts{
QueryLimit: QueryLImit,
ExcelMaxRow: ExcelMaxRow,
Tag: "export",
}
func NewExportOpts(query, limit int, path string) *ExportOpts {
return &ExportOpts{
QueryLimit: query,
ExcelMaxRow: limit,
Path: path,
}
}

159
biz/direct.go Normal file
View File

@ -0,0 +1,159 @@
package biz
import (
"context"
"excel_export/data"
"excel_export/export"
"fmt"
"time"
)
func NewDirectBiz(repo *data.DirectRepo, historyRepo *data.HistoryDirectRepo, opts *ExportOpts) *DirectBiz {
biz := &DirectBiz{
repo: repo,
historyRepo: historyRepo,
}
if opts == nil {
opts = DefaultOpts
}
opts.Tag = "direct"
biz.opts = opts
return biz
}
type DirectBiz struct {
repo *data.DirectRepo
historyRepo *data.HistoryDirectRepo
baseExportBiz
}
func (e *DirectBiz) FileSize() int {
return e.fileSize
}
func (e *DirectBiz) Export(begin, end time.Time) error {
e.setFileArg(begin)
file := export.NewExport(e.fileName, e.opts.ExcelMaxRow)
if err := file.Open(); err != nil {
return err
}
if err := file.Title(export.Directs{}.Title()); err != nil {
return err
}
//导出历史订单数据
if err := e.exportHistoryData(file, begin, end); err != nil {
return err
}
//导出最近7天数据
if err := e.exportData(file, begin, end); err != nil {
return err
}
e.fileSize = file.Index()
return nil
}
func (e *DirectBiz) exportHistoryData(export *export.Export, begin, end time.Time) error {
var last string
for true {
//导出最近7天数据
data, err := e.historyRepo.List(context.Background(), begin, end, e.opts.QueryLimit, last)
if err != nil {
return fmt.Errorf("获取导出数据错误:%w", err)
}
if err := export.Export(e.HistoryTransforms(data)); err != nil {
return err
}
if len(data) < e.opts.QueryLimit {
return nil
}
last = data[len(data)-1].SerialNumber
}
return nil
}
func (e *DirectBiz) exportData(export *export.Export, begin, end time.Time) error {
var last string
for true {
//导出最近7天数据
data, err := e.repo.List(context.Background(), begin, end, e.opts.QueryLimit, last)
if err != nil {
return fmt.Errorf("获取导出数据错误:%w", err)
}
if err := export.Export(e.Transforms(data)); err != nil {
return err
}
if len(data) < e.opts.QueryLimit {
return nil
}
last = data[len(data)-1].SerialNumber
}
return nil
}
func (e DirectBiz) Transforms(data []data.Direct) export.Directs {
result := make(export.Directs, len(data))
for i, val := range data {
result[i] = e.Transform(val)
}
return result
}
func (e DirectBiz) Transform(data data.Direct) *export.Direct {
return &export.Direct{
ResellerId: data.Order.ResellerId,
ResellerName: data.Order.Reseller.Name,
ResellerOrderNumber: data.Order.ResellerOrderNumber,
OursProductId: data.OursProductId,
OursProductTitle: data.OrderItem.OursProductTitle,
PlatformName: data.PlatformProduct.Platform.Name,
PlatformProductCode: data.PlatformProduct.Code,
PlatformProductName: data.PlatformProduct.Name,
Status: data.Status,
OrderOrderNumber: data.OrderOrderNumber,
SerialNumber: data.SerialNumber,
TerminalAccount: data.TerminalAccount,
TradePrice: data.TradePrice,
PlatformPrice: data.PlatformPrice,
CreateTime: data.CreateTime.Format("2006-01-02 15:04:05"),
ExecuteTime: data.ExecuteTime.Format("2006-01-02 15:04:05"),
Remark: data.Order.Remark.Remark,
}
}
func (e DirectBiz) HistoryTransforms(data []data.HistoryDirect) export.Directs {
result := make(export.Directs, len(data))
for i, val := range data {
result[i] = e.HistoryTransform(val)
}
return result
}
func (e DirectBiz) HistoryTransform(data data.HistoryDirect) *export.Direct {
return &export.Direct{
ResellerId: data.Order.ResellerId,
ResellerName: data.Order.Reseller.Name,
ResellerOrderNumber: data.Order.ResellerOrderNumber,
OursProductId: data.OursProductId,
OursProductTitle: data.OrderItem.OursProductTitle,
PlatformName: data.PlatformProduct.Platform.Name,
PlatformProductCode: data.PlatformProduct.Code,
PlatformProductName: data.PlatformProduct.Name,
Status: data.Status,
OrderOrderNumber: data.OrderOrderNumber,
SerialNumber: data.SerialNumber,
TerminalAccount: data.TerminalAccount,
TradePrice: data.TradePrice,
PlatformPrice: data.PlatformPrice,
CreateTime: data.CreateTime.Format("2006-01-02 15:04:05"),
ExecuteTime: data.ExecuteTime.Format("2006-01-02 15:04:05"),
Remark: data.Order.Remark.Remark,
}
}

36
biz/direct_test.go Normal file
View File

@ -0,0 +1,36 @@
package biz
import (
"excel_export/data"
"fmt"
"github.com/stretchr/testify/assert"
"os"
"testing"
"time"
)
func directBiz() *DirectBiz {
db := data.Conn()
repo := data.NewDirectRepo(db)
historyRepo := data.NewHistoryDirectRepo(db)
return NewDirectBiz(repo, historyRepo, nil)
}
func TestDirectBiz_Export(t *testing.T) {
biz := directBiz()
begin := time.Date(2022, 10, 1, 0, 0, 0, 0, time.Local)
end := time.Date(2022, 12, 1, 0, 0, 0, 0, time.Local)
err := biz.Export(begin, end)
assert.Nil(t, err)
for i := 0; i <= biz.FileSize(); i++ {
fileName := fmt.Sprintf(biz.FileName(), i)
assert.FileExists(t, fileName)
//清理文件
os.Remove(fileName)
}
}

150
biz/order.go Normal file
View File

@ -0,0 +1,150 @@
package biz
import (
"context"
"excel_export/data"
"excel_export/export"
"fmt"
"time"
)
func NewOrderBiz(repo *data.OrderRepo, historyRepo *data.HistoryOrderRepo, opts *ExportOpts) *OrderBiz {
biz := &OrderBiz{
repo: repo,
historyRepo: historyRepo,
}
biz.opts = DefaultOpts
if opts != nil {
biz.opts = opts
}
return biz
}
type OrderBiz struct {
repo *data.OrderRepo
historyRepo *data.HistoryOrderRepo
baseExportBiz
}
func (e *OrderBiz) Export(begin, end time.Time) error {
e.setFileArg(begin)
file := export.NewExport(e.fileName, e.opts.ExcelMaxRow)
if err := file.Open(); err != nil {
return err
}
if err := file.Title(export.Orders{}.Title()); err != nil {
return err
}
//导出历史订单数据
if err := e.exportHistoryData(file, begin, end); err != nil {
return err
}
//导出最近7天数据
if err := e.exportData(file, begin, end); err != nil {
return err
}
e.fileSize = file.Index()
return nil
}
func (e *OrderBiz) exportHistoryData(export *export.Export, begin, end time.Time) error {
var last string
for true {
//导出最近7天数据
data, err := e.historyRepo.List(context.Background(), begin, end, e.opts.QueryLimit, last)
if err != nil {
return fmt.Errorf("获取导出数据错误:%w", err)
}
if err := export.Export(e.HistoryTransforms(data)); err != nil {
return err
}
if len(data) < e.opts.QueryLimit {
return nil
}
last = data[len(data)-1].OrderNumber
}
return nil
}
func (e *OrderBiz) exportData(export *export.Export, begin, end time.Time) error {
var last string
for true {
//导出最近7天数据
data, err := e.repo.List(context.Background(), begin, end, e.opts.QueryLimit, last)
if err != nil {
return fmt.Errorf("获取导出数据错误:%w", err)
}
if err := export.Export(e.Transforms(data)); err != nil {
return err
}
if len(data) < e.opts.QueryLimit {
return nil
}
last = data[len(data)-1].OrderNumber
}
return nil
}
func (e OrderBiz) Transforms(data []data.Order) export.Orders {
result := make(export.Orders, len(data))
for i, val := range data {
result[i] = e.Transform(val)
}
return result
}
func (e OrderBiz) Transform(order data.Order) *export.Order {
return &export.Order{
OrderNumber: order.OrderNumber,
ResellerId: order.ResellerId,
ResellerName: order.Reseller.Name,
ResellerOrderNumber: order.ResellerOrderNumber,
Amount: order.Amount,
Account: order.Account,
Quantity: order.Quantity,
Status: order.Status,
PayStatus: order.PayStatus,
CreateTime: time.Unix(order.CreateTime, 0).Format("2006-01-02 15:04:05"),
FinishTime: time.Unix(order.FinishTime, 0).Format("2006-01-02 15:04:05"),
OursProductId: order.Item.OursProductId,
OursProductTitle: order.Item.OursProductTitle,
Remark: order.Remark.Remark,
}
}
func (e OrderBiz) HistoryTransforms(data []data.HistoryOrder) export.Orders {
result := make(export.Orders, len(data))
for i, val := range data {
result[i] = e.HistoryTransform(val)
}
return result
}
func (e OrderBiz) HistoryTransform(order data.HistoryOrder) *export.Order {
return &export.Order{
OrderNumber: order.OrderNumber,
ResellerId: order.ResellerId,
ResellerName: order.Reseller.Name,
ResellerOrderNumber: order.ResellerOrderNumber,
Amount: order.Amount,
Account: order.Account,
Quantity: order.Quantity,
Status: order.Status,
PayStatus: order.PayStatus,
CreateTime: order.CreateTime.Format("2006-01-02 15:04:05"),
FinishTime: order.FinishTime.Format("2006-01-02 15:04:05"),
OursProductId: order.Item.OursProductId,
OursProductTitle: order.Item.OursProductTitle,
Remark: order.Remark.Remark,
}
}

35
biz/order_test.go Normal file
View File

@ -0,0 +1,35 @@
package biz
import (
"excel_export/data"
"fmt"
"github.com/stretchr/testify/assert"
"os"
"testing"
"time"
)
func orderBiz() *OrderBiz {
db := data.Conn()
repo := data.NewOrderRepo(db)
historyRepo := data.NewHistoryOrderRepo(db)
return NewOrderBiz(repo, historyRepo, nil)
}
func TestOrderBiz_Export(t *testing.T) {
biz := orderBiz()
begin := time.Date(2022, 8, 1, 0, 0, 0, 0, time.UTC)
end := time.Date(2022, 8, 2, 10, 0, 0, 0, time.UTC)
err := biz.Export(begin, end)
assert.Nil(t, err)
for i := 0; i <= biz.FileSize(); i++ {
fileName := fmt.Sprintf(biz.FileName(), i)
assert.FileExists(t, fileName)
//清理文件
os.Remove(fileName)
}
}

35
cmd/cmd/order.go Normal file
View File

@ -0,0 +1,35 @@
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)
}
}

28
cmd/cmd/root.go Normal file
View File

@ -0,0 +1,28 @@
package cmd
import (
"github.com/spf13/cobra"
"os"
)
var rootCmd = &cobra.Command{
Use: "export",
Short: "导出直充系统订单数据",
SilenceUsage: true,
SilenceErrors: true,
}
func Execute() {
path, _ := os.Getwd()
rootCmd.PersistentFlags().StringP("path", "p", path, "文件路径")
rootCmd.PersistentFlags().IntP("query", "q", 10000, "单次查询数")
rootCmd.PersistentFlags().IntP("limit", "l", 1000000, "单个文档最大记录数")
OrderCmd.Flags().StringP("begin", "b", "", "开始时间2006-01-02 15:04:05")
OrderCmd.Flags().StringP("end", "e", "", "结束时间2006-01-02 15:04:05")
rootCmd.AddCommand(OrderCmd)
cobra.CheckErr(rootCmd.Execute())
}

49
cmd/cmd/uitls.go Normal file
View File

@ -0,0 +1,49 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"
"os"
"time"
)
func MustFlagsDateTime(cmd *cobra.Command, key string) time.Time {
t, err := ParseFlagsDateTime(cmd.Flags(), key)
cobra.CheckErr(err)
return *t
}
func ParseFlagsDateTime(set *flag.FlagSet, key string) (*time.Time, error) {
val, err := set.GetString(key)
if err != nil {
return nil, fmt.Errorf("获取参数异常:%w", err)
}
beginTime, err := time.Parse("2006-01-02 15:04:05", val)
if err != nil {
return nil, fmt.Errorf("不是有效的时间格式:%w", err)
}
return &beginTime, nil
}
func CmdOutput(cmd *cobra.Command, format string, opts ...interface{}) {
fmt.Fprintf(cmd.OutOrStdout(), format, opts...)
}
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,7 +1,9 @@
package main package main
func main() { import "excel_export/cmd/cmd"
func main() {
cmd.Execute()
} }
//分块获取数据 //分块获取数据

17
data/batch.go Normal file
View File

@ -0,0 +1,17 @@
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,24 +1,63 @@
package data package data
import "time" import (
"context"
"gorm.io/gorm"
"time"
)
type Card struct { type Card struct {
OrderNumber string OrderNumber string `gorm:"primaryKey;column:order_number"`
ResellerId int ResellerId int `gorm:"column:reseller_id"`
ResellerOrderNumber string ResellerOrderNumber string `gorm:"column:reseller_order_number"`
OursProductId int OursProductId int `gorm:"column:ours_product_id"`
Price float32 Price float32 `gorm:"column:price"`
Quantity int Quantity int `gorm:"column:quantity"`
Amount float32 Amount float32 `gorm:"column:amount"`
PayStatus int PayStatus int `gorm:"column:pay_status"`
Status int Status int `gorm:"column:status"`
Profit float32 Profit float32 `gorm:"column:profit"`
NotifyUrl string NotifyTime int64 `gorm:"column:notify_time"`
NotifyTime time.Time CreateIp int64 `gorm:"column:create_ip"`
CreateIp int CreateTime int64 `gorm:"column:create_time"`
CreateTime time.Time CardCode string `gorm:"column:card_code"`
CardCode string FinishTime time.Time `gorm:"column:finish_time"`
FinishTime time.Time Message string `gorm:"column:message"`
Message string Mobile string `gorm:"column:mobile"`
Mobile string 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
} }

24
data/card_test.go Normal file
View File

@ -0,0 +1,24 @@
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)
}

40
data/common.go Normal file
View File

@ -0,0 +1,40 @@
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

@ -10,5 +10,5 @@ func Conn() *gorm.DB {
if err != nil { if err != nil {
panic("数据库连接失败") panic("数据库连接失败")
} }
return conn return conn //.Debug()
} }

View File

@ -1,15 +1,10 @@
package data package data
import "time" import (
"context"
type PlatformProduct struct { "gorm.io/gorm"
Id int64 "time"
Name string )
}
func (p PlatformProduct) TableName() string {
return "platform_product"
}
type Direct struct { type Direct struct {
SerialNumber string `gorm:"primaryKey;column:serial_number"` SerialNumber string `gorm:"primaryKey;column:serial_number"`
@ -26,10 +21,67 @@ type Direct struct {
Version int `gorm:"column:version"` Version int `gorm:"column:version"`
Type int `gorm:"column:type"` Type int `gorm:"column:type"`
Position int `gorm:"column:position"` 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"` OrderItem OrderItem `gorm:"foreignkey:order_order_number;references:order_order_number"`
PlatformProduct PlatformProduct `gorm:"foreignkey:id;references:platform_product_id"` PlatformProduct PlatformProduct `gorm:"foreignkey:id;references:platform_product_id"`
Batch Batch `gorm:"foreignkey:batch_id;references:order_order_number"`
} }
func (d Direct) TableName() string { func (d Direct) TableName() string {
return "order_direct" 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
}

33
data/direct_test.go Normal file
View File

@ -0,0 +1,33 @@
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)
}

87
data/history_direct.go Normal file
View File

@ -0,0 +1,87 @@
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
}

77
data/history_order.go Normal file
View File

@ -0,0 +1,77 @@
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

@ -6,15 +6,6 @@ import (
"time" "time"
) )
type Reseller struct {
Id int64 `gorm:"primaryKey;column:id"`
Name string
}
func (o Reseller) TableName() string {
return "reseller"
}
type OrderItem struct { type OrderItem struct {
OrderNumber string `gorm:"primaryKey;column:order_order_number"` OrderNumber string `gorm:"primaryKey;column:order_order_number"`
OursProductId int OursProductId int
@ -66,7 +57,7 @@ func NewOrderRepo(db *gorm.DB) *OrderRepo {
func (repo OrderRepo) List(ctx context.Context, begin, end time.Time, limit int, last string) ([]Order, error) { func (repo OrderRepo) List(ctx context.Context, begin, end time.Time, limit int, last string) ([]Order, error) {
var orders []Order var orders []Order
db := repo.db.WithContext(ctx).Debug(). db := repo.db.WithContext(ctx).
Preload("Reseller"). Preload("Reseller").
Preload("Item"). Preload("Item").
Preload("Remark"). Preload("Remark").

57
export/batch.go Normal file
View File

@ -0,0 +1,57 @@
package export
type Batch struct {
ResellerId int
ResellerName string
OursProductId int
OursProductTitle string
PlatformName string
PlatformProductCode string
PlatformProductName string
Status int
OrderOrderNumber string
SerialNumber string
TerminalAccount string
TradePrice float32
PlatformPrice float32
CreateTime string
ExecuteTime string
DingTalkSn string
Remark string
}
type Batchs []*Batch
func (o Batchs) Title() []string {
return []string{
"分销商id",
"分销商名称",
"我们的商品id",
"订单商品名称",
"接口平台",
"接口平台产品编码",
"接口平台产品名称",
"充值状态",
"系统订单号",
"流水号",
"充值账号",
"成交价格",
"接口平台价格",
"创建时间",
"执行时间",
"钉钉审批序号",
"批量备注",
}
}
func (o Batchs) Size() int {
return len(o)
}
func (o Batchs) Data() []interface{} {
d := make([]interface{}, o.Size())
for i, v := range o {
d[i] = v
}
return d
}

43
export/card.go Normal file
View File

@ -0,0 +1,43 @@
package export
type Card struct {
OrderNumber string
ResellerOrderNumber string
Amount float32
Quantity int
Status int
ResellerId int
ResellerName string
OursProductId int
OursProductTitle string
CreateTime string
}
type Cards []*Card
func (o Cards) Title() []string {
return []string{
"订单号",
"分销商订单号",
"扣款价格",
"数量",
"充值状态",
"分销商编号",
"分销商名称",
"订单商品编号",
"订单商品名称",
"创建时间",
}
}
func (o Cards) Size() int {
return len(o)
}
func (o Cards) Data() []interface{} {
d := make([]interface{}, o.Size())
for i, v := range o {
d[i] = v
}
return d
}

57
export/direct.go Normal file
View File

@ -0,0 +1,57 @@
package export
type Direct struct {
ResellerId int64
ResellerName string
ResellerOrderNumber string
OursProductId int
OursProductTitle string
PlatformName string
PlatformProductCode string
PlatformProductName string
Status int
OrderOrderNumber string
SerialNumber string
TerminalAccount string
TradePrice float32
PlatformPrice float32
CreateTime string
ExecuteTime string
Remark string
}
type Directs []*Direct
func (o Directs) Title() []string {
return []string{
"分销商id",
"分销商名称",
"商户订单号",
"我们的商品id",
"订单商品名称",
"接口平台",
"接口平台产品编码",
"接口平台产品名称",
"充值状态",
"系统订单号",
"流水号",
"充值账号",
"成交价格",
"接口平台价格",
"创建时间",
"执行时间",
"备注",
}
}
func (o Directs) Size() int {
return len(o)
}
func (o Directs) Data() []interface{} {
d := make([]interface{}, o.Size())
for i, v := range o {
d[i] = v
}
return d
}

View File

@ -58,25 +58,29 @@ func (e *Export) slice() {
} }
func (e *Export) reset() { func (e *Export) reset() {
e.Save() e.save()
e.index++ e.index++
e.Open() e.Open()
e.Title(nil) e.Title(nil)
e.slice() e.slice()
} }
func (e Export) Index() int {
return e.index
}
func (e *Export) Export(data Entity) error { func (e *Export) Export(data Entity) error {
if e.file == nil || e.sheet == nil { if e.file == nil || e.sheet == nil {
return errors.New("没有执行open方法") return errors.New("没有执行open方法")
} }
e.count = data.Size() e.count = e.count + data.Size()
for _, order := range data.Data() { for _, order := range data.Data() {
e.slice() e.slice()
row := e.sheet.AddRow() row := e.sheet.AddRow()
row.WriteStruct(order, -1) row.WriteStruct(order, -1)
} }
return nil return e.save()
} }
func (e *Export) Open() error { func (e *Export) Open() error {
@ -124,6 +128,6 @@ func (e *Export) isFielExist(file string) (bool, error) {
return false, err return false, err
} }
func (e *Export) Save() error { func (e *Export) save() error {
return e.file.Save(e.fileName()) return e.file.Save(e.fileName())
} }

View File

@ -3,6 +3,7 @@ package export
import ( import (
"excel_export/data" "excel_export/data"
"fmt" "fmt"
"github.com/stretchr/testify/assert"
"os" "os"
"testing" "testing"
) )
@ -12,7 +13,7 @@ func TestExport_Export(t *testing.T) {
path := dir + "/aa_%d.xlsx" path := dir + "/aa_%d.xlsx"
e := NewExport(path, 4) e := NewExport(path, 4)
err := e.Open() err := e.Open()
fmt.Println(err) assert.Nil(t, err)
data := NewOrder([]data.Order{ data := NewOrder([]data.Order{
{ {
@ -216,11 +217,15 @@ func TestExport_Export(t *testing.T) {
}) })
err = e.Title(data.Title()) err = e.Title(data.Title())
fmt.Println(err) assert.Nil(t, err)
err = e.Export(data) err = e.Export(data)
fmt.Println(err) assert.Nil(t, err)
for i := 0; i <= e.Index(); i++ {
file := fmt.Sprintf(path, i)
assert.FileExists(t, file)
os.Remove(file)
}
err = e.Save()
fmt.Println(err)
} }

9
go.mod
View File

@ -6,20 +6,29 @@ require (
github.com/tealeg/xlsx/v3 v3.2.4 // direct github.com/tealeg/xlsx/v3 v3.2.4 // direct
gorm.io/driver/mysql v1.4.5 // direct gorm.io/driver/mysql v1.4.5 // direct
gorm.io/gorm v1.24.3 // direct gorm.io/gorm v1.24.3 // direct
github.com/spf13/cobra v1.6.1 // direct
) )
require github.com/stretchr/testify v1.8.1
require ( require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/frankban/quicktest v1.11.2 // indirect github.com/frankban/quicktest v1.11.2 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/google/btree v1.0.0 // indirect github.com/google/btree v1.0.0 // indirect
github.com/google/go-cmp v0.5.2 // indirect github.com/google/go-cmp v0.5.2 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jinzhu/now v1.1.5 // indirect
github.com/kr/pretty v0.2.1 // indirect github.com/kr/pretty v0.2.1 // indirect
github.com/kr/text v0.1.0 // indirect github.com/kr/text v0.1.0 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // 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/fastuuid v1.2.0 // indirect
github.com/shabbyrobe/xmlwriter v0.0.0-20200208144257-9fca06d00ffa // indirect github.com/shabbyrobe/xmlwriter v0.0.0-20200208144257-9fca06d00ffa // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/text v0.3.3 // indirect golang.org/x/text v0.3.3 // indirect
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
) )