|
|
@@ -1,58 +1,442 @@
|
|
|
package one2many
|
|
|
|
|
|
import (
|
|
|
- "encoding/json"
|
|
|
"git.sxidc.com/go-framework/baize/convenient/binding"
|
|
|
"git.sxidc.com/go-framework/baize/convenient/binding/request"
|
|
|
+ "git.sxidc.com/go-framework/baize/convenient/binding/response"
|
|
|
"git.sxidc.com/go-framework/baize/framwork/api"
|
|
|
"git.sxidc.com/go-framework/baize/framwork/domain"
|
|
|
+ "git.sxidc.com/go-framework/baize/framwork/domain/entity"
|
|
|
"git.sxidc.com/go-framework/baize/framwork/infrastructure"
|
|
|
+ "git.sxidc.com/go-framework/baize/framwork/infrastructure/database"
|
|
|
+ "git.sxidc.com/go-framework/baize/framwork/infrastructure/database/sql"
|
|
|
+ "git.sxidc.com/go-framework/baize/framwork/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(tableName string) binding.ServiceFunc[any] {
|
|
|
+func UpdateLeft(leftTableName string, leftDomainCNName string, leftRelationFieldName string,
|
|
|
+ rightTableName 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(leftEntity.DomainCNName())
|
|
|
+ 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("部分{{ $toCNName }}不存在")
|
|
|
+ }
|
|
|
+
|
|
|
+ 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](tableName string) binding.ServiceFunc[RI] {
|
|
|
- return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (RI, error) {
|
|
|
- var info RI
|
|
|
- return info, 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.Query)
|
|
|
+ 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(tableName string) binding.ServiceFunc[any] {
|
|
|
+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(rightEntity.DomainCNName())
|
|
|
+ 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](tableName string) binding.ServiceFunc[LI] {
|
|
|
+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) {
|
|
|
- var info LI
|
|
|
- return info, nil
|
|
|
+ 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存在性校验
|
|
|
+ rightExist, err := database.CheckExist(dbExecutor, &sql.CheckExistExecuteParams{
|
|
|
+ TableName: rightTableName,
|
|
|
+ Conditions: sql.NewConditions().Equal(entity.ColumnID, rightEntity.GetID()),
|
|
|
+ })
|
|
|
+ if err != nil {
|
|
|
+ return outputZero, err
|
|
|
+ }
|
|
|
+
|
|
|
+ if !rightExist {
|
|
|
+ return outputZero, fserr.New(rightEntity.DomainCNName() + "不存在")
|
|
|
+ }
|
|
|
+
|
|
|
+ if !domain.HasField(object, rightRelationFieldName) {
|
|
|
+ return outputZero, fserr.New("关联字段" + rightRelationFieldName + "不存在")
|
|
|
+ }
|
|
|
+
|
|
|
+ leftID, err := domain.Field[string](object, 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
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func QueryRightWithLeftInfo[RI any, LI any](tableName string) binding.ServiceFunc[map[string]any] {
|
|
|
+func QueryRightWithLeftInfo[RI any, LI any](rightTableName string, leftTableName string) binding.ServiceFunc[map[string]any] {
|
|
|
return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (map[string]any, error) {
|
|
|
- info := new(struct {
|
|
|
- Self RI `json:"self"`
|
|
|
- With LI `json:"with"`
|
|
|
- })
|
|
|
+ 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.Query)
|
|
|
+ if !ok {
|
|
|
+ return errResponse, fserr.New("请求参数不是Query接口")
|
|
|
+ }
|
|
|
+
|
|
|
+ fromEntity, ok := object.(entity.Entity)
|
|
|
+ if !ok {
|
|
|
+ return errResponse, fserr.New("领域对象不是实体")
|
|
|
+ }
|
|
|
|
|
|
- infoJson, err := json.Marshal(info)
|
|
|
+ conditions := sql.NewConditions()
|
|
|
+
|
|
|
+ fromFields, err := sql_mapping.DefaultUsage(fromEntity)
|
|
|
if err != nil {
|
|
|
- return nil, err
|
|
|
+ return errResponse, err
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, fromField := range fromFields {
|
|
|
+ hasDeal := false
|
|
|
+ if fromFieldCallback != nil {
|
|
|
+ hasDeal = fromFieldCallback(conditions, fromField.FieldName, fromField.ColumnName, fromField.Value)
|
|
|
+ }
|
|
|
+
|
|
|
+ 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
|
|
|
}
|
|
|
|
|
|
- retMap := make(map[string]any)
|
|
|
- err = json.Unmarshal(infoJson, &retMap)
|
|
|
+ toIDs := make([]string, 0)
|
|
|
+ for _, fromResult := range fromResults {
|
|
|
+ toID := fromResult.ColumnValueString(fromRelationColumnName)
|
|
|
+ if strutils.IsStringNotEmpty(toID) {
|
|
|
+ toIDs = append(toIDs, toID)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ toResults, _, err := database.Query(dbExecutor, &sql.QueryExecuteParams{
|
|
|
+ TableName: toTableName,
|
|
|
+ Conditions: sql.NewConditions().In(entity.ColumnID, toIDs),
|
|
|
+ })
|
|
|
if err != nil {
|
|
|
- return nil, err
|
|
|
+ return errResponse, err
|
|
|
+ }
|
|
|
+
|
|
|
+ toResultMap := make(map[string]sql.Result)
|
|
|
+ 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[FI]()
|
|
|
+
|
|
|
+ err = sql.ParseSqlResult(fromResult, &fromInfo)
|
|
|
+ if err != nil {
|
|
|
+ return errResponse, err
|
|
|
+ }
|
|
|
+
|
|
|
+ toID := fromResult.ColumnValueString(fromRelationColumnName)
|
|
|
+ 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 retMap, nil
|
|
|
+ return response.InfosData[map[string]any]{
|
|
|
+ Infos: infos,
|
|
|
+ TotalCount: totalCount,
|
|
|
+ PageNo: queryParams.GetPageNo(),
|
|
|
+ }, nil
|
|
|
}
|
|
|
}
|