table_append_data_to_table_service.go 6.5 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/repository"
	"time"
)

type AppendDataToTableService struct {
	transactionContext *pgTransaction.TransactionContext
}

// AppendData 追加数据 【data-table】
func (ptr *AppendDataToTableService) AppendData(ctx *domain.Context, fileId int, tableId int, mappingFields []*domain.MappingField) (interface{}, error) {
	fileRepository, _ := repository.NewFileRepository(ptr.transactionContext)
	file, err := fileRepository.FindOne(map[string]interface{}{"fileId": fileId})
	if err != nil {
		return nil, fmt.Errorf("文件不存在")
	}
	tableRepository, _ := repository.NewTableRepository(ptr.transactionContext)
	table, err := tableRepository.FindOne(map[string]interface{}{"tableId": tableId})
	if err != nil {
		return nil, fmt.Errorf("表不存在")
	}
	defer func() {
		AsyncEvent(domain.NewEventTable(ctx, domain.TableDataImportEvent).WithTable(table))
	}()
	excelTable, err := tableRepository.FindOne(map[string]interface{}{"tableId": file.FileInfo.TableId})
	if err != nil {
		return nil, fmt.Errorf("文件未校验")
	}

	if !(table.TableType == domain.MainTable.ToString() || table.TableType == domain.SideTable.ToString()) {
		return nil, fmt.Errorf("只能追加数据到主表或者副表")
	}
	var subTables []*domain.Table
	_, subTables, err = tableRepository.Find(map[string]interface{}{"parentId": tableId, "tableTypes": []string{domain.SubTable.ToString()}})
	if err != nil {
		return nil, err
	}

	// 更新表数据
	table.RowCount += excelTable.RowCount
	table.UpdatedAt = time.Now()
	if _, err = tableRepository.Save(table); err != nil {
		return nil, err
	}

	// 日志
	entry := domain.NewLogEntry(table.Name, domain.MainTable.ToString(), domain.AppendData, ctx)
	if err = FastLog(ptr.transactionContext, domain.CommonLog, table.TableId, &AppendDataToTableLog{
		LogEntry:  (&entry).WithAppendFileId(fileId),
		File:      file,
		Table:     table,
		SubTables: subTables,
		RowCount:  excelTable.RowCount,
	}); err != nil {
		return nil, err
	}

	// 通知底层进行追加数据
	requestData := domain.ReqAppendData{Table: table, FileId: fileId, FileUrl: file.FileInfo.Url, ExcelTable: excelTable}
	if len(mappingFields) > 0 {
		for _, m := range mappingFields {
			var toField, fromField *domain.Field
			var ok bool
			toField, ok = table.MatchField(m.MainTableField)
			if !ok {
				continue
			}
			if len(m.VerifiedFileFieldName) == 0 {
				fromField = &domain.Field{}
				// continue
			} else {
				fromField, ok = excelTable.MatchField(&domain.Field{Name: m.VerifiedFileFieldName})
				if !ok {
					continue
				}
			}
			if fromField.SQLType != "" && !toField.SqlTypeEqual(fromField) {
				//return nil, fmt.Errorf("字段【%s】的类型与导入数据表的类型不匹配", toField.Name)
				return map[string]interface{}{
					"result": fmt.Sprintf("字段【%s】的类型与导入数据表的类型不匹配", toField.Name),
				}, nil
			}
			fromField.SQLType = toField.SQLType // 兼容 INT BIGINT
			requestData.To = append(requestData.To, toField)
			requestData.From = append(requestData.From, fromField)
		}
	}
	if _, err = ByteCore.AppendData(requestData); err != nil {
		return nil, err
	}
	return map[string]interface{}{
		"result": fmt.Sprintf("源数据%v条,成功追加%v条;", excelTable.RowCount, excelTable.RowCount),
	}, nil
}

// AppendDataDirectly 直接追加数据
func (ptr *AppendDataToTableService) AppendDataDirectly(ctx *domain.Context, fileUrl string, table *domain.Table, mappingFields []*domain.MappingField) (interface{}, error) {
	defer func() {
		//AsyncEvent(domain.NewEventTable(ctx, domain.TableDataImportEvent).WithTable(table))
	}()
	if !(table.TableType == domain.MainTable.ToString() || table.TableType == domain.SideTable.ToString()) {
		return nil, fmt.Errorf("只能追加数据到主表或者副表")
	}
	var err error
	// 通知底层进行追加数据
	requestData := domain.ReqAppendData{Table: table, FileId: int(time.Now().Unix()), FileUrl: fileUrl, ExcelTable: table}
	if len(mappingFields) > 0 {
		for _, m := range mappingFields {
			var toField, fromField *domain.Field
			var ok bool
			toField, ok = table.MatchField(m.MainTableField)
			if !ok {
				continue
			}
			if len(m.VerifiedFileFieldName) == 0 {
				fromField = &domain.Field{}
			} else {
				fromField, ok = table.MatchField(&domain.Field{Name: m.VerifiedFileFieldName})
				if !ok {
					continue
				}
			}
			if fromField.SQLType != "" && !toField.SqlTypeEqual(fromField) {
				//return nil, fmt.Errorf("字段【%s】的类型与导入数据表的类型不匹配", toField.Name)
				return map[string]interface{}{
					"result": fmt.Sprintf("字段【%s】的类型与导入数据表的类型不匹配", toField.Name),
				}, nil
			}
			fromField.SQLType = toField.SQLType // 兼容 INT BIGINT
			requestData.To = append(requestData.To, toField)
			requestData.From = append(requestData.From, fromField)
		}
	}
	if _, err = ByteCore.AppendData(requestData); err != nil {
		return nil, err
	}
	return nil, nil
}

// PreflightCheck 预检
func (ptr *AppendDataToTableService) PreflightCheck(ctx *domain.Context, fileId int, tableId int, mappingFields []*domain.MappingField) (interface{}, error) {
	tableRepository, _ := repository.NewTableRepository(ptr.transactionContext)
	table, err := tableRepository.FindOne(map[string]interface{}{"tableId": tableId})
	if err != nil {
		return nil, fmt.Errorf("表不存在")
	}
	inSourceId := []int{table.TableId}
	if table.ParentId != 0 {
		inSourceId = append(inSourceId, table.ParentId)
	}
	logRepository, _ := repository.NewLogRepository(ptr.transactionContext)
	_, logs, err := logRepository.Find(map[string]interface{}{
		"inSourceId":      inSourceId,
		"inOperationType": []string{domain.GenerateMainTable.ToString(), domain.AppendData.ToString()},
		"limit":           500,
	})
	if err != nil {
		return nil, err
	}

	for _, log := range logs {
		if log.Entry.AppendFileId == fileId {
			return map[string]interface{}{
				"fileAppended": true,
			}, nil
		}
	}
	return map[string]interface{}{
		"fileAppended": false,
	}, nil
}

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