package one2one import ( "git.sxidc.com/go-framework/baize/framework/binding" "git.sxidc.com/go-framework/baize/framework/core/api" "git.sxidc.com/go-framework/baize/framework/core/api/request" "git.sxidc.com/go-framework/baize/framework/core/api/response" "git.sxidc.com/go-framework/baize/framework/core/domain" "git.sxidc.com/go-framework/baize/framework/core/domain/entity" "git.sxidc.com/go-framework/baize/framework/core/infrastructure" "git.sxidc.com/go-framework/baize/framework/core/infrastructure/database" "git.sxidc.com/go-framework/baize/framework/core/infrastructure/database/sql" "git.sxidc.com/go-framework/baize/framework/core/tag/sql/sql_mapping" "git.sxidc.com/go-tools/utils/reflectutils" "git.sxidc.com/go-tools/utils/strutils" "github.com/pkg/errors" "reflect" ) func Update(fromTableName string, fromRelationFieldName string, fromRelationColumnName string, toTableName string, toDomainCNName string, toRelationColumnName string) binding.ServiceFunc[any] { return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) { object := objects[0] if object == nil { return nil, errors.New("领域实体为空") } dbExecutor := i.DBExecutor() fromEntity, ok := object.(entity.Entity) if !ok { return nil, errors.New("领域对象不是实体") } // 字段校验 err := domain.CheckField(fromEntity, entity.FieldID, fromEntity.GetFieldMap()) if err != nil { return nil, err } // from存在性校验 fromResult, err := database.QueryOne(dbExecutor, &sql.QueryOneExecuteParams{ TableName: fromTableName, Conditions: sql.NewConditions().Equal(entity.ColumnID, fromEntity.GetID()), }) if err != nil { if database.IsErrorDBRecordNotExist(err) { return nil, errors.New(fromEntity.DomainCNName() + "不存在") } return nil, err } if !domain.HasField(object, fromRelationFieldName) { return nil, errors.New("关联字段" + fromRelationFieldName + "不存在") } existFrom := reflect.New(reflect.TypeOf(object).Elem()).Interface().(domain.Object) err = sql.ParseSqlResult(fromResult, existFrom) if err != nil { return nil, err } currentToID, err := domain.Field[string](existFrom, fromRelationFieldName) if err != nil { return nil, err } newToID, err := domain.Field[string](object, fromRelationFieldName) if err != nil { return nil, err } if strutils.IsStringNotEmpty(newToID) { // to存在性校验 toExist, err := database.CheckExist(dbExecutor, &sql.CheckExistExecuteParams{ TableName: toTableName, Conditions: sql.NewConditions().Equal(entity.ColumnID, newToID), }) if err != nil { return nil, err } if !toExist { return nil, errors.New(fromEntity.DomainCNName() + "关联的" + toDomainCNName + "不存在") } } err = database.Transaction(dbExecutor, func(tx database.Executor) error { if strutils.IsStringNotEmpty(fromTableName) { err := database.Update(tx, &sql.UpdateExecuteParams{ TableName: fromTableName, TableRow: sql.NewTableRow().Add(toRelationColumnName, newToID), Conditions: sql.NewConditions().Equal(entity.ColumnID, fromEntity.GetID()), }) if err != nil { return err } } if strutils.IsStringNotEmpty(toTableName) && (strutils.IsStringNotEmpty(currentToID) || strutils.IsStringNotEmpty(newToID)) { fromID := fromEntity.GetID() if strutils.IsStringEmpty(newToID) { fromID = "" } updateToID := currentToID if strutils.IsStringEmpty(currentToID) { updateToID = newToID } err := database.Update(tx, &sql.UpdateExecuteParams{ TableName: toTableName, TableRow: sql.NewTableRow().Add(fromRelationColumnName, fromID), Conditions: sql.NewConditions().Equal(entity.ColumnID, updateToID), }) if err != nil { return err } } return nil }) if err != nil { return nil, err } return nil, nil } } func Query[TI any](fromTableName string, fromRelationFieldName string, toTableName string) binding.ServiceFunc[TI] { return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (TI, error) { outputZero := reflectutils.Zero[TI]() object := objects[0] if object == nil { return outputZero, errors.New("领域实体为空") } dbExecutor := i.DBExecutor() fromEntity, ok := object.(entity.Entity) if !ok { return outputZero, errors.New("领域对象不是实体") } // from存在性校验 existFromResult, err := database.QueryOne(dbExecutor, &sql.QueryOneExecuteParams{ TableName: fromTableName, Conditions: sql.NewConditions().Equal(entity.ColumnID, fromEntity.GetID()), }) if err != nil { if database.IsErrorDBRecordNotExist(err) { return outputZero, errors.New(fromEntity.DomainCNName() + "不存在") } return outputZero, err } existFromEntity := reflect.New(reflect.TypeOf(object).Elem()).Interface().(domain.Object) err = sql.ParseSqlResult(existFromResult, existFromEntity) if err != nil { return outputZero, err } if !domain.HasField(existFromEntity, fromRelationFieldName) { return outputZero, errors.New("关联字段" + fromRelationFieldName + "不存在") } toID, err := domain.Field[string](existFromEntity, fromRelationFieldName) if err != nil { return outputZero, err } toResult, err := database.QueryOne(dbExecutor, &sql.QueryOneExecuteParams{ TableName: toTableName, Conditions: sql.NewConditions().Equal(entity.ColumnID, toID), }) if err != nil && !database.IsErrorDBRecordNotExist(err) { return outputZero, err } info := reflectutils.Zero[TI]() err = sql.ParseSqlResult(toResult, &info) if err != nil { return outputZero, err } return info, nil } } type ConditionFieldCallback func(conditions *sql.Conditions, fieldName string, columnName string, value any) (hasDeal bool, err error) func QueryWithOtherInfo[FI any, TI any](fromTableName string, fromFieldCallback ConditionFieldCallback, toTableName string, toRelationColumnName string) binding.ServiceFunc[response.InfosData[map[string]any]] { return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (response.InfosData[map[string]any], error) { errResponse := response.InfosData[map[string]any]{ Infos: make([]map[string]any, 0), } if params == nil { return errResponse, errors.New("请求参数为空") } object := objects[0] if object == nil { return errResponse, errors.New("领域实体为空") } dbExecutor := i.DBExecutor() queryParams, ok := params.(request.QueryRequestParams) if !ok { return errResponse, errors.New("请求参数不是Query接口") } fromEntity, ok := object.(entity.Entity) if !ok { return errResponse, errors.New("领域对象不是实体") } conditions := sql.NewConditions() fromFields, err := sql_mapping.DefaultUsage(fromEntity) if err != nil { return errResponse, err } for _, fromField := range fromFields { hasDeal := false if fromFieldCallback != nil { hasDeal, err = fromFieldCallback(conditions, fromField.FieldName, fromField.ColumnName, fromField.Value) if err != nil { return errResponse, err } } if !hasDeal { fieldValue := reflect.ValueOf(fromField.Value) if !fieldValue.IsZero() { conditions.Equal(fromField.ColumnName, fromField.Value) } } } fromResults, totalCount, err := database.Query(dbExecutor, &sql.QueryExecuteParams{ TableName: fromTableName, Conditions: conditions, PageNo: queryParams.GetPageNo(), PageSize: queryParams.GetPageSize(), }) if err != nil { return errResponse, nil } if fromResults == nil || len(fromResults) == 0 { return response.InfosData[map[string]any]{ Infos: make([]map[string]any, 0), TotalCount: 0, PageNo: 0, }, nil } toIDs := make([]string, 0) for _, fromResult := range fromResults { toID := fromResult.ColumnValueString(toRelationColumnName) if strutils.IsStringNotEmpty(toID) { toIDs = append(toIDs, toID) } } toResultMap := make(map[string]sql.Result) if toIDs != nil && len(toIDs) != 0 { toResults, _, err := database.Query(dbExecutor, &sql.QueryExecuteParams{ TableName: toTableName, Conditions: sql.NewConditions().In(entity.ColumnID, toIDs), }) if err != nil { return errResponse, err } for _, toResult := range toResults { toID := toResult.ColumnValueString(entity.ColumnID) toResultMap[toID] = toResult } } infos := make([]map[string]any, len(fromResults)) for index, fromResult := range fromResults { fromInfo := reflectutils.Zero[FI]() toInfo := reflectutils.Zero[TI]() err = sql.ParseSqlResult(fromResult, &fromInfo) if err != nil { return errResponse, err } toID := fromResult.ColumnValueString(toRelationColumnName) if strutils.IsStringEmpty(toID) { infos[index] = map[string]any{ "self": fromInfo, "with": toInfo, } continue } toResult, ok := toResultMap[toID] if !ok { infos[index] = map[string]any{ "self": fromInfo, "with": toInfo, } continue } err = sql.ParseSqlResult(toResult, &toInfo) if err != nil { return errResponse, err } infos[index] = map[string]any{ "self": fromInfo, "with": toInfo, } } return response.InfosData[map[string]any]{ Infos: infos, TotalCount: totalCount, PageNo: queryParams.GetPageNo(), }, nil } }