package one2many 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/slice" "git.sxidc.com/go-tools/utils/strutils" "github.com/pkg/errors" "reflect" ) func UpdateLeft(leftTableName string, leftDomainCNName string, leftRelationFieldName string, leftRelationColumnName string, rightTableName string, rightDomainCNName 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() leftEntity, ok := object.(entity.Entity) if !ok { return nil, errors.New("领域对象不是实体") } // 字段校验 err := domain.CheckField(leftEntity, entity.FieldID, leftEntity.GetFieldMap()) if err != nil { return nil, err } // left存在性校验 leftExist, err := database.CheckExist(dbExecutor, &sql.CheckExistExecuteParams{ TableName: leftTableName, Conditions: sql.NewConditions().Equal(entity.ColumnID, leftEntity.GetID()), }) if err != nil { return nil, err } if !leftExist { return nil, errors.New(leftEntity.DomainCNName() + "不存在") } if !domain.HasField(object, leftRelationFieldName) { return nil, errors.New("关联字段" + leftRelationFieldName + "不存在") } rightIDs, err := domain.Field[[]string](object, leftRelationFieldName) if err != nil { return nil, err } if rightIDs != nil && len(rightIDs) != 0 { for _, rightID := range rightIDs { err := entity.CheckIDTypeValue(leftDomainCNName, leftRelationFieldName, rightID) if err != nil { return nil, err } } rightIDs = slice.RemoveRepeatElement(rightIDs) } err = database.Transaction(dbExecutor, func(tx database.Executor) error { err := database.Update(tx, &sql.UpdateExecuteParams{ TableName: rightTableName, TableRow: sql.NewTableRow().Add(leftRelationColumnName, ""), Conditions: sql.NewConditions().Equal(leftRelationColumnName, leftEntity.GetID()), }) if err != nil { return err } if rightIDs == nil || len(rightIDs) == 0 { return nil } rightCount, err := database.Count(dbExecutor, &sql.CountExecuteParams{ TableName: rightTableName, Conditions: sql.NewConditions().In(entity.ColumnID, rightIDs), }) if err != nil { return err } if int(rightCount) != len(rightIDs) { return errors.New("部分" + rightDomainCNName + "不存在") } err = database.Update(tx, &sql.UpdateExecuteParams{ TableName: rightTableName, TableRow: sql.NewTableRow().Add(leftRelationColumnName, leftEntity.GetID()), Conditions: sql.NewConditions().In(entity.ColumnID, rightIDs), }) if err != nil { return err } return nil }) if err != nil { return nil, err } return nil, nil } } func QueryLeft[RI any](leftTableName string, leftRelationColumnName string, rightTableName string, leftQueryOrderBy string) binding.ServiceFunc[response.InfosData[RI]] { return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (response.InfosData[RI], error) { errResponse := response.InfosData[RI]{ Infos: make([]RI, 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.QueryWithIDRequestParams) if !ok { return errResponse, errors.New("请求参数不是Query接口") } leftEntity, ok := object.(entity.Entity) if !ok { return errResponse, errors.New("领域对象不是实体") } // left存在性校验 leftExist, err := database.CheckExist(dbExecutor, &sql.CheckExistExecuteParams{ TableName: leftTableName, Conditions: sql.NewConditions().Equal(entity.ColumnID, leftEntity.GetID()), }) if err != nil { return errResponse, err } if !leftExist { return errResponse, errors.New(leftEntity.DomainCNName() + "不存在") } rightResults, totalCount, err := database.Query(dbExecutor, &sql.QueryExecuteParams{ TableName: rightTableName, Conditions: sql.NewConditions().Equal(leftRelationColumnName, leftEntity.GetID()), OrderBy: leftQueryOrderBy, }) if err != nil && !database.IsErrorDBRecordNotExist(err) { return errResponse, err } infos := make([]RI, 0) err = sql.ParseSqlResult(rightResults, &infos) if err != nil { return errResponse, err } return response.InfosData[RI]{ Infos: infos, TotalCount: totalCount, PageNo: queryParams.GetPageNo(), }, nil } } func UpdateRight(rightTableName string, rightRelationFieldName string, leftTableName string, leftDomainCNName string, leftRelationColumnName 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() rightEntity, ok := object.(entity.Entity) if !ok { return nil, errors.New("领域对象不是实体") } // 字段校验 err := domain.CheckField(rightEntity, entity.FieldID, rightEntity.GetFieldMap()) if err != nil { return nil, err } // right存在性校验 rightExist, err := database.CheckExist(dbExecutor, &sql.CheckExistExecuteParams{ TableName: rightTableName, Conditions: sql.NewConditions().Equal(entity.ColumnID, rightEntity.GetID()), }) if err != nil { return nil, err } if !rightExist { return nil, errors.New(rightEntity.DomainCNName() + "不存在") } if !domain.HasField(object, rightRelationFieldName) { return nil, errors.New("关联字段" + rightRelationFieldName + "不存在") } leftID, err := domain.Field[string](object, rightRelationFieldName) if err != nil { return nil, err } if strutils.IsStringNotEmpty(leftID) { leftExist, err := database.CheckExist(dbExecutor, &sql.CheckExistExecuteParams{ TableName: leftTableName, Conditions: sql.NewConditions().Equal(entity.ColumnID, leftID), }) if err != nil { return nil, err } if !leftExist { return nil, errors.New(leftDomainCNName + "不存在") } } err = database.Update(dbExecutor, &sql.UpdateExecuteParams{ TableName: rightTableName, TableRow: sql.NewTableRow().Add(leftRelationColumnName, leftID), Conditions: sql.NewConditions().Equal(entity.ColumnID, rightEntity.GetID()), }) if err != nil { return nil, err } return nil, nil } } func QueryRight[LI any](rightTableName string, rightRelationFieldName string, leftTableName string) binding.ServiceFunc[LI] { return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (LI, error) { outputZero := reflectutils.Zero[LI]() dbExecutor := i.DBExecutor() object := objects[0] if object == nil { return outputZero, errors.New("领域实体为空") } rightEntity, ok := object.(entity.Entity) if !ok { return outputZero, errors.New("领域对象不是实体") } // right存在性校验 existRightResult, err := database.QueryOne(dbExecutor, &sql.QueryOneExecuteParams{ TableName: rightTableName, Conditions: sql.NewConditions().Equal(entity.ColumnID, rightEntity.GetID()), }) if err != nil { if database.IsErrorDBRecordNotExist(err) { return outputZero, errors.New(rightEntity.DomainCNName() + "不存在") } return outputZero, err } existRightEntity := reflect.New(reflect.TypeOf(object).Elem()).Interface().(domain.Object) err = sql.ParseSqlResult(existRightResult, existRightEntity) if err != nil { return outputZero, err } if !domain.HasField(existRightEntity, rightRelationFieldName) { return outputZero, errors.New("关联字段" + rightRelationFieldName + "不存在") } leftID, err := domain.Field[string](existRightEntity, rightRelationFieldName) if err != nil { return outputZero, err } leftResult, err := database.QueryOne(dbExecutor, &sql.QueryOneExecuteParams{ TableName: leftTableName, Conditions: sql.NewConditions().Equal(entity.ColumnID, leftID), }) if err != nil && !database.IsErrorDBRecordNotExist(err) { return outputZero, err } leftInfo := reflectutils.Zero[LI]() err = sql.ParseSqlResult(leftResult, &leftInfo) if err != nil { return outputZero, err } return leftInfo, nil } } type ConditionFieldCallback func(conditions *sql.Conditions, fieldName string, columnName string, value any) (hasDeal bool, err error) func QueryRightWithLeftInfo[RI any, LI any](rightTableName string, rightFieldCallback ConditionFieldCallback, leftTableName string, leftRelationColumnName 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接口") } rightEntity, ok := object.(entity.Entity) if !ok { return errResponse, errors.New("领域对象不是实体") } conditions := sql.NewConditions() rightFields, err := sql_mapping.DefaultUsage(rightEntity) if err != nil { return errResponse, err } for _, rightField := range rightFields { hasDeal := false if rightFieldCallback != nil { hasDeal, err = rightFieldCallback(conditions, rightField.FieldName, rightField.ColumnName, rightField.Value) if err != nil { return errResponse, err } } if !hasDeal { fieldValue := reflect.ValueOf(rightField.Value) if !fieldValue.IsZero() { conditions.Equal(rightField.ColumnName, rightField.Value) } } } rightResults, totalCount, err := database.Query(dbExecutor, &sql.QueryExecuteParams{ TableName: rightTableName, Conditions: conditions, PageNo: queryParams.GetPageNo(), PageSize: queryParams.GetPageSize(), }) if err != nil { return errResponse, nil } if rightResults == nil || len(rightResults) == 0 { return response.InfosData[map[string]any]{ Infos: make([]map[string]any, 0), TotalCount: 0, PageNo: 0, }, nil } leftIDs := make([]string, 0) for _, rightResult := range rightResults { leftID := rightResult.ColumnValueString(leftRelationColumnName) if strutils.IsStringNotEmpty(leftID) { leftIDs = append(leftIDs, leftID) } } leftResultMap := make(map[string]sql.Result) if leftIDs != nil && len(leftIDs) != 0 { leftResults, _, err := database.Query(dbExecutor, &sql.QueryExecuteParams{ TableName: leftTableName, Conditions: sql.NewConditions().In(entity.ColumnID, leftIDs), }) if err != nil { return errResponse, err } for _, leftResult := range leftResults { leftID := leftResult.ColumnValueString(entity.ColumnID) leftResultMap[leftID] = leftResult } } infos := make([]map[string]any, len(rightResults)) for index, rightResult := range rightResults { rightInfo := reflectutils.Zero[RI]() leftInfo := reflectutils.Zero[LI]() err = sql.ParseSqlResult(rightResult, &rightInfo) if err != nil { return errResponse, err } leftID := rightResult.ColumnValueString(leftRelationColumnName) if strutils.IsStringEmpty(leftID) { infos[index] = map[string]any{ "self": rightInfo, "with": leftInfo, } continue } leftResult, ok := leftResultMap[leftID] if !ok { infos[index] = map[string]any{ "self": rightInfo, "with": leftInfo, } continue } err = sql.ParseSqlResult(leftResult, &leftInfo) if err != nil { return errResponse, err } infos[index] = map[string]any{ "self": rightInfo, "with": leftInfo, } } return response.InfosData[map[string]any]{ Infos: infos, TotalCount: totalCount, PageNo: queryParams.GetPageNo(), }, nil } }