package one2many import ( "git.sxidc.com/go-framework/baize/framework/binding" "git.sxidc.com/go-framework/baize/framework/binding/request" "git.sxidc.com/go-framework/baize/framework/binding/response" "git.sxidc.com/go-framework/baize/framework/core/api" "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" "git.sxidc.com/service-supports/fserr" "reflect" ) func UpdateLeft(leftTableName string, leftDomainCNName string, leftRelationFieldName string, rightTableName string, rightDomainCNName string, rightRelationColumnName 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, fserr.New("领域实体为空") } dbExecutor := i.DBExecutor() leftEntity, ok := object.(entity.Entity) if !ok { return nil, fserr.New("领域对象不是实体") } // 字段校验 err := leftEntity.CheckFieldID() 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, fserr.New(leftEntity.DomainCNName() + "不存在") } if !domain.HasField(object, leftRelationFieldName) { return nil, fserr.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.CheckID(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(rightRelationColumnName, ""), Conditions: sql.NewConditions().Equal(rightRelationColumnName, 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 fserr.New("部分" + rightDomainCNName + "不存在") } err = database.Update(tx, &sql.UpdateExecuteParams{ TableName: rightTableName, TableRow: sql.NewTableRow().Add(rightRelationColumnName, 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, rightTableName string, rightRelationColumnName 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, fserr.New("请求参数为空") } object := objects[0] if object == nil { return errResponse, fserr.New("领域实体为空") } dbExecutor := i.DBExecutor() queryParams, ok := params.(request.QueryWithIDRequestParams) if !ok { return errResponse, fserr.New("请求参数不是Query接口") } leftEntity, ok := object.(entity.Entity) if !ok { return errResponse, fserr.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, fserr.New(leftEntity.DomainCNName() + "不存在") } rightResults, totalCount, err := database.Query(dbExecutor, &sql.QueryExecuteParams{ TableName: rightTableName, Conditions: sql.NewConditions().Equal(rightRelationColumnName, leftEntity.GetID()), }) 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, rightRelationColumnName string, leftTableName string, leftDomainCNName 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, fserr.New("领域实体为空") } dbExecutor := i.DBExecutor() rightEntity, ok := object.(entity.Entity) if !ok { return nil, fserr.New("领域对象不是实体") } // 字段校验 err := rightEntity.CheckFieldID() 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, fserr.New(rightEntity.DomainCNName() + "不存在") } if !domain.HasField(object, rightRelationFieldName) { return nil, fserr.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, fserr.New(leftDomainCNName + "不存在") } } err = database.Update(dbExecutor, &sql.UpdateExecuteParams{ TableName: rightTableName, TableRow: sql.NewTableRow().Add(rightRelationColumnName, 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, fserr.New("领域实体为空") } rightEntity, ok := object.(entity.Entity) if !ok { return outputZero, fserr.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, fserr.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, fserr.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) func QueryRightWithLeftInfo[RI any, LI any](rightTableName string, rightRelationColumnName string, rightFieldCallback ConditionFieldCallback, leftTableName 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, fserr.New("请求参数为空") } object := objects[0] if object == nil { return errResponse, fserr.New("领域实体为空") } dbExecutor := i.DBExecutor() queryParams, ok := params.(request.QueryRequestParams) if !ok { return errResponse, fserr.New("请求参数不是Query接口") } rightEntity, ok := object.(entity.Entity) if !ok { return errResponse, fserr.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 = rightFieldCallback(conditions, rightField.FieldName, rightField.ColumnName, rightField.Value) } 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(rightRelationColumnName) 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(rightRelationColumnName) 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 } }