file_table_preview_data_table_service.go 7.1 KB
package domainService

import (
	"fmt"
	pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
	"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
	"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/api/bytelib"
	"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/redis"
	"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/repository"
)

type PreviewDataTableService struct {
	FileId             int
	transactionContext *pgTransaction.TransactionContext
}

// RePreview 重新预览,表头重置时,前端调用重新预览接口,重置缓存的表头行号
func (ptr *PreviewDataTableService) RePreview(ctx *domain.Context, fileId int, fields []*domain.Field, where domain.Where) (interface{}, error) {
	fileRepository, _ := repository.NewFileRepository(ptr.transactionContext)
	file, err := fileRepository.FindOne(map[string]interface{}{"fileId": fileId})
	if err != nil {
		return nil, fmt.Errorf("校验文件不存在")
	}
	isSourceFile := true
	fileUrl := file.FileInfo.Url
	fileCache := redis.NewFileCacheService()
	tempFile, _ := fileCache.Get(redis.KeyTemporaryFileInfo(fileId))
	if tempFile == nil {
		return nil, fmt.Errorf("临时文件不存在")
	}
	// Load Data From Excel(python api)
	byteCore, _ := CreateByteCoreService()
	response, err := byteCore.LoadDataTable(domain.ReqLoadDataTable{
		FileId:              file.FileId,
		FileName:            file.FileInfo.Name,
		Url:                 file.FileInfo.Url,
		Ext:                 file.FileInfo.Ext,
		Where:               where,
		OriginalTableId:     fmt.Sprintf("%v", file.FileId),
		IsFromOriginalTable: isSourceFile,
		TableFileUrl:        fileUrl,
		ColumnSchemas:       bytelib.DomainFieldsToColumnSchemas(fields),
		SortParameters:      make(map[string]interface{}),
	})
	if err != nil {
		return nil, err
	}
	// 强制刷新列
	fields = response.Fields

	cache := redis.NewFileCacheService()
	tempFile, err = cache.Update(redis.KeyTemporaryFileInfo(file.FileId), file, fields, response.Total, redis.WithHeaderRow(where.HeaderRow))
	if err != nil {
		return nil, err
	}
	var responseDto = &FilePreviewDto{}
	//responseDto.Load(file.FileId, response, tempFile)
	return responseDto, nil
}

// Preview 预览  【data-table】
func (ptr *PreviewDataTableService) Preview(ctx *domain.Context, fileId int, fields []*domain.Field, where domain.Where) (interface{}, error) {
	fileRepository, _ := repository.NewFileRepository(ptr.transactionContext)
	file, err := fileRepository.FindOne(map[string]interface{}{"fileId": fileId})
	if err != nil {
		return nil, fmt.Errorf("校验文件不存在")
	}
	isSourceFile := true
	fileUrl := file.FileInfo.Url
	if file.FileType != domain.TemporaryFile.ToString() {
		return nil, fmt.Errorf("校验文件不存在")
	}
	ptr.FileId = file.FileId
	fileCache := redis.NewFileCacheService()
	if tempFile, _ := fileCache.Get(redis.KeyTemporaryFileInfo(fileId)); tempFile != nil {
		isSourceFile = false
		fields = tempFile.Fields
	} else if file.SourceFileId > 0 {
		sourceFile, err := fileRepository.FindOne(map[string]interface{}{"fileId": file.SourceFileId})
		if err != nil {
			return nil, fmt.Errorf("校验文件源文件不存在")
		}
		tableRepository, _ := repository.NewTableRepository(ptr.transactionContext)
		table, _ := tableRepository.FindOne(map[string]interface{}{"tableId": sourceFile.FileInfo.TableId})
		if table != nil {
			fields = table.Fields(false)
		}
	}

	// Load Data From Excel(python api)
	byteCore, _ := CreateByteCoreService()
	response, err := byteCore.LoadDataTable(domain.ReqLoadDataTable{
		FileId:              file.FileId,
		FileName:            file.FileInfo.Name,
		Url:                 file.FileInfo.Url,
		Ext:                 file.FileInfo.Ext,
		Where:               where,
		OriginalTableId:     fmt.Sprintf("%v", file.FileId),
		IsFromOriginalTable: isSourceFile,
		TableFileUrl:        fileUrl,
		ColumnSchemas:       bytelib.DomainFieldsToColumnSchemas(fields),
		SortParameters:      make(map[string]interface{}),
	})
	if err != nil {
		return nil, err
	}
	if len(fields) == 0 {
		fields = response.Fields
	}
	cache := redis.NewFileCacheService()
	tempFile, err := cache.Update(redis.KeyTemporaryFileInfo(file.FileId), file, fields, response.Total)
	if err != nil {
		return nil, err
	}
	var responseDto = &FilePreviewDto{}
	responseDto.Load(file.FileId, response, tempFile)
	return responseDto, nil
}

func (ptr *PreviewDataTableService) CreateTemporaryFile(ctx *domain.Context, fileId int) (*domain.File, error) {
	fileRepository, _ := repository.NewFileRepository(ptr.transactionContext)
	file, err := fileRepository.FindOne(map[string]interface{}{"fileId": fileId})
	if err != nil {
		return nil, fmt.Errorf("文件不存在")
	}
	if !(file.FileType == domain.SourceFile.ToString() || file.FileType == domain.VerifiedFile.ToString()) {
		return nil, fmt.Errorf("源文件/校验文件才可以创建临时文件")
	}
	file = file.CopyTo(domain.TemporaryFile, ctx)
	file.FileInfo.TableId = 0
	if file, err = fileRepository.Save(file); err != nil {
		return nil, err
	}
	return file, nil
}

type FilePreviewDto struct {
	ObjectId     int                  `json:"objectId"`
	ObjectType   string               `json:"objectType"`
	TableType    string               `json:"tableType"`
	Fields       []*domain.Field      `json:"fields"`
	Data         interface{}          `json:"grid"`
	PageNumber   int                  `json:"pageNumber"`
	InValidCells []domain.InValidCell `json:"inValidCells"`
	HeaderRow    int                  `json:"headerRow"`
}

func (d *FilePreviewDto) Load(fileId int, m *domain.DataLoadDataTable, file *redis.TemporaryFileInfo) {
	d.ObjectId = fileId
	d.ObjectType = domain.ObjectFile
	d.TableType = domain.ExcelTable.ToString()
	for i, f := range file.Fields {
		d.Fields = append(d.Fields, &domain.Field{
			Index:   i + 1,
			Name:    f.Name,
			SQLName: f.Name,
			SQLType: f.SQLType,
		})
	}

	var fields []*domain.Field
	mapData := domain.ToFieldData(file.Fields, formatData(m.Data, func(s string) string {
		if s == "<NA>" {
			return ""
		}
		if s == "nan" {
			return ""
		}
		return s
	}), true)
	d.Data = domain.GripData(mapData, int64(m.Total))
	d.PageNumber = m.PageNumber

	for _, f := range file.Fields {
		copyField := f.Copy()
		for _, e := range file.ConvertTypeErrors {
			if e.FieldName == copyField.Name {
				copyField.SQLType = e.ToType
			}
		}
		fields = append(fields, copyField)
	}

	d.InValidCells = domain.NewInValidCells(fields, mapData)
	d.HeaderRow = domain.GetHeaderRow(file.HeaderRow)
}

func (ptr *PreviewDataTableService) GetFileId() int {
	return ptr.FileId
}

func formatData(data [][]string, f func(s string) string) [][]string {
	for i := 0; i < len(data); i++ {
		for j := 0; j < len(data[i]); j++ {
			data[i][j] = f(data[i][j])
		}
	}
	return data
}

func NewLoadDataTableService(transactionContext *pgTransaction.TransactionContext) (*PreviewDataTableService, error) {
	if transactionContext == nil {
		return nil, fmt.Errorf("transactionContext参数不能为nil")
	} else {
		return &PreviewDataTableService{
			transactionContext: transactionContext,
		}, nil
	}
}