kjt 4 месяцев назад
Родитель
Сommit
ae4f1782f6

+ 19 - 0
.gitignore

@@ -0,0 +1,19 @@
+# Binaries for programs and plugins
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, build with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+.idea/
+.DS_Store
+**/bin
+
+/vendor/
+**/logs

+ 68 - 0
application/application.go

@@ -0,0 +1,68 @@
+package application
+
+import (
+	"ecos/application/service"
+	"ecos/config"
+	"git.sxidc.co
+	"net/http"
+)
+
+var appInstance *application.App
+
+func NewApp() {
+	if appInstance != nil {
+		return
+	}
+
+	appInstance = baize.NewApplication(config.GetConfig().ApplicationConfig)
+
+	// 注册Router
+	appInstance.Api().PrefixRouter().RegisterVersionedRouter("v1")
+}
+
+func DestroyApp() {
+	if appInstance == nil {
+		return
+	}
+
+	baize.DestroyApplication(appInstance)
+	appInstance = nil
+}
+
+func Start() error {
+	// 初始化服务
+	for _, svc := range service.RegisteredServices {
+		err := svc.Init(appInstance)
+		if err != nil {
+			return err
+		}
+	}
+
+	err := appInstance.Start()
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func Finish() error {
+	err := appInstance.Finish()
+	if err != nil {
+		return err
+	}
+
+	// 销毁服务
+	for _, svc := range service.RegisteredServices {
+		err := svc.Destroy()
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func ServerHttpForTest(w http.ResponseWriter, req *http.Request) {
+	appInstance.Api().RootRouter().(*api.RootRouter).ServerHttp(w, req)
+}

+ 61 - 0
application/domain/shop_decoration/entity.go

@@ -0,0 +1,61 @@
+package shop_decoration
+
+import (
+	"git.sxidc.com/go-framework/baize/framework/core/domain"
+	"git.sxidc.com/go-framework/baize/framework/core/domain/entity"
+)
+
+const (
+	FieldName           = "Name"
+	FieldPageClientType = "PageClientType"
+	FieldPageData       = "PageData"
+	FieldPageType       = "PageType"
+	FieldPageShow       = "PageShow"
+)
+
+var fieldMap = map[string]string{
+	FieldName:           "页面名称",
+	FieldPageClientType: "客户端类型",
+	FieldPageData:       "页面数据",
+	FieldPageType:       "页面类型",
+	FieldPageShow:       "页面开关状态",
+}
+
+var (
+	ColumnName           = domain.ColumnName(FieldName)
+	ColumnPageClientType = domain.ColumnName(FieldPageClientType)
+	ColumnPageData       = domain.ColumnName(FieldPageData)
+	ColumnPageType       = domain.ColumnName(FieldPageType)
+	ColumnPageShow       = domain.ColumnName(FieldPageShow)
+)
+
+type Entity struct {
+	entity.Base
+	Name           string `sqlmapping:"column:name;" sqlresult:"column:name;" check:"FlashSaleProductInfolte=255,when=create/update"`
+	PageClientType string `sqlmapping:"column:page_client_type;" sqlresult:"column:page_client_type;" check:"FlashSaleProductInfolte=32,when=create/update"`
+	PageData       string `sqlmapping:"column:page_data;" sqlresult:"column:page_data;" check:"FlashSaleProductInfowhen=create/update"`
+	PageType       string `sqlmapping:"column:page_type;" sqlresult:"column:page_type;" check:"FlashSaleProductInfolte=32,when=create/update"`
+	PageShow       string `sqlmapping:"column:page_show;" sqlresult:"column:page_show;" check:"FlashSaleProductInfolte=32,when=create/update"`
+	entity.TenantIDField
+	entity.UserIDFields
+	entity.OperatorUserNameField
+	entity.TimeFields
+
+	/* HAC: ENTITY RELATION FIELDS */
+	/* HAC: END ENTITY RELATION FIELDS */
+}
+
+func (e *Entity) DomainCNName() string {
+	return "店铺装修列表"
+}
+
+func (e *Entity) DomainCamelName() string {
+	return "ShopDecoration"
+}
+
+func (e *Entity) GetFieldMap() map[string]string {
+	return fieldMap
+}
+
+/* HAC: ENTITY RELATION METHODS */
+/* HAC: END ENTITY RELATION METHODS */

+ 17 - 0
application/domain/shop_decoration/info.go

@@ -0,0 +1,17 @@
+package shop_decoration
+
+import (
+	"git.sxidc.com/go-framework/baize/framework/core/application"
+)
+
+type Info struct {
+	application.InfoIDField
+	Name           string `json:"name" sqlresult:"column:name;"`
+	PageClientType string `json:"pageClientType" sqlresult:"column:page_client_type;"`
+	PageData       string `json:"pageData" sqlresult:"column:page_data;"`
+	PageType       string `json:"pageType" sqlresult:"column:page_type;"`
+	PageShow       string `json:"pageShow" sqlresult:"column:page_show;"`
+	application.InfoTenantIDField
+	application.InfoUserIDFields
+	application.InfoTimeFields
+}

+ 52 - 0
application/domain/shop_decoration/request_params.go

@@ -0,0 +1,52 @@
+package shop_decoration
+
+import (
+	"git.sxidc.com/go-framework/baize/framework/core/api/request"
+)
+
+type (
+	CreateShopDecorationJsonBody struct {
+		Name           string `json:"name" binding:"required" assign:"toField:Name"`
+		PageClientType string `json:"pageClientType" binding:"required" assign:"toField:PageClientType"`
+		PageData       string `json:"pageData" binding:"required" assign:"toField:PageData"`
+		PageType       string `json:"pageType" binding:"required" assign:"toField:PageType"`
+		PageShow       string `json:"pageShow" assign:"toField:PageShow"`
+		request.TenantIDJsonBody
+		request.CreateUserIDJsonBody
+		request.OperatorUserNameJsonBody
+	}
+
+	DeleteShopDecorationQueryParams struct {
+		request.IDQueryParam
+		request.DeleteUserIDQueryParams
+		request.OperatorUserNameQueryParams
+	}
+
+	UpdateShopDecorationJsonBody struct {
+		request.IDJsonBody
+		Name           string `json:"name" assign:"toField:Name"`
+		PageClientType string `json:"pageClientType" assign:"toField:PageClientType"`
+		PageData       string `json:"pageData" assign:"toField:PageData"`
+		PageType       string `json:"pageType" assign:"toField:PageType"`
+		PageShow       string `json:"pageShow" assign:"toField:PageShow"`
+		request.UpdateUserIDJsonBody
+		request.OperatorUserNameJsonBody
+	}
+
+	GetShopDecorationsQueryParams struct {
+		request.BaseQueryParams
+		request.TenantIDQueryParam
+		Name           string `form:"name" ecosassign:"toField:Name"`
+		PageClientType string `form:"pageClientType" ecosassign:"toField:PageClientType"`
+		PageData       string `form:"pageData" ecosassign:"toField:PageData"`
+		PageType       string `form:"pageType" ecosassign:"toField:PageType"`
+		PageShow       string `form:"pageShow" ecosassign:"toField:PageShow"`
+	}
+
+	GetShopDecorationQueryParams struct {
+		request.IDQueryParam
+	}
+
+	/* HAC: HTTP RELATION REQUEST PARAMS */
+	/* HAC: END HTTP RELATION REQUEST PARAMS */
+)

+ 25 - 0
application/service/configuration.go

@@ -0,0 +1,25 @@
+package service
+
+import (
+	"git.sxidc.com/go-framework/baize/convenient/domain/configuration"
+	"git.sxidc.com/go-framework/baize/framework/core/application"
+)
+
+var configurationService = &ConfigurationService{}
+
+type ConfigurationService struct{}
+
+func (svc *ConfigurationService) Init(appInstance *application.App) error {
+	svc.prefixRoot(appInstance)
+	return nil
+}
+
+func (svc *ConfigurationService) Destroy() error {
+	return nil
+}
+
+func (svc *ConfigurationService) prefixRoot(appInstance *application.App) {
+	configuration.Bind(appInstance, &configuration.Simple{
+		Schema: dbSchema,
+	})
+}

+ 25 - 0
application/service/operate_log.go

@@ -0,0 +1,25 @@
+package service
+
+import (
+	"git.sxidc.com/go-framework/baize/convenient/domain/operate_log"
+	"git.sxidc.com/go-framework/baize/framework/core/application"
+)
+
+var operateLogService = &OperateLogService{}
+
+type OperateLogService struct{}
+
+func (svc *OperateLogService) Init(appInstance *application.App) error {
+	svc.prefixRoot(appInstance)
+	return nil
+}
+
+func (svc *OperateLogService) Destroy() error {
+	return nil
+}
+
+func (svc *OperateLogService) prefixRoot(appInstance *application.App) {
+	operate_log.Bind(appInstance, &operate_log.Simple{
+		Schema: dbSchema,
+	})
+}

+ 24 - 0
application/service/service.go

@@ -0,0 +1,24 @@
+package service
+
+import (
+	"git.sxidc.com/go-framework/baize/framework/core/application"
+)
+
+const (
+	dbSchema = "pcs"
+)
+
+type Service interface {
+	Init(appInstance *application.App) error
+	Destroy() error
+}
+
+var RegisteredServices = []Service{
+	/* HAC: REGISTER SERVICE */
+	versionService,
+	sqlExecutorService,
+	configurationService,
+	operateLogService,
+	shopDecorationService,
+	/* HAC: END REGISTER SERVICE */
+}

+ 80 - 0
application/service/shop_decoration.go

@@ -0,0 +1,80 @@
+package service
+
+import (
+	"ecos/application/domain/shop_decoration"
+	"git.sxidc.com/go-framework/baize/convenient/entity_crud"
+	"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/application"
+	"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/database"
+	"git.sxidc.com/go-framework/baize/framework/core/infrastructure/database/sql"
+	"github.com/pkg/errors"
+)
+
+var shopDecorationService = &ShopDecorationService{}
+
+type ShopDecorationService struct{}
+
+func (svc *ShopDecorationService) Init(appInstance *application.App) error {
+	svc.v1(appInstance)
+	return nil
+}
+
+func (svc *ShopDecorationService) Destroy() error {
+	return nil
+}
+
+func (svc *ShopDecorationService) v1(appInstance *application.App) {
+	v1Binder := binding.NewBinder(appInstance.ChooseRouter(api.RouterPrefix, "v1"),
+		appInstance.Infrastructure())
+
+	entity_crud.BindSimple[shop_decoration.Info](v1Binder, &entity_crud.Simple[shop_decoration.Info]{
+		Entity:             &shop_decoration.Entity{},
+		Schema:             dbSchema,
+		CreateJsonBody:     &shop_decoration.CreateShopDecorationJsonBody{},
+		DeleteQueryParams:  &shop_decoration.DeleteShopDecorationQueryParams{},
+		UpdateJsonBody:     &shop_decoration.UpdateShopDecorationJsonBody{},
+		QueryQueryParams:   &shop_decoration.GetShopDecorationsQueryParams{},
+		GetByIDQueryParams: &shop_decoration.GetShopDecorationQueryParams{},
+	}, entity_crud.WithQueryStringFieldQueryCondition[shop_decoration.Info](entity_crud.StringFieldQueryConditionTrimSpaceLike))
+}
+
+func (svc *ShopDecorationService) queryByKeyFields(e *shop_decoration.Entity, dbExecutor database.Executor) (*shop_decoration.Entity, error) {
+	result, err := database.QueryOne(dbExecutor, &sql.QueryOneExecuteParams{
+		TableName:  domain.TableName(dbSchema, e),
+		Conditions: sql.NewConditions().Equal(entity.ColumnID, e.ID),
+	})
+	if err != nil {
+		if database.IsErrorDBRecordNotExist(err) {
+			return nil, errors.New(e.DomainCNName() + "不存在")
+		}
+
+		return nil, err
+	}
+
+	existEntity := new(shop_decoration.Entity)
+	err = sql.ParseSqlResult(result, existEntity)
+	if err != nil {
+		return nil, err
+	}
+
+	return existEntity, nil
+}
+
+func (svc *ShopDecorationService) checkExistByKeyFields(e *shop_decoration.Entity, dbExecutor database.Executor) error {
+	exist, err := database.CheckExist(dbExecutor, &sql.CheckExistExecuteParams{
+		TableName:  domain.TableName(dbSchema, e),
+		Conditions: sql.NewConditions().Equal(entity.ColumnID, e.ID),
+	})
+	if err != nil {
+		return err
+	}
+
+	if !exist {
+		return errors.New(e.DomainCNName() + "不存在")
+	}
+
+	return nil
+}

+ 25 - 0
application/service/sql_executor.go

@@ -0,0 +1,25 @@
+package service
+
+import (
+	"git.sxidc.com/go-framework/baize/convenient/domain/sql_executor"
+	"git.sxidc.com/go-framework/baize/framework/core/application"
+)
+
+var sqlExecutorService = &SqlExecutorService{}
+
+type SqlExecutorService struct{}
+
+func (svc *SqlExecutorService) Init(appInstance *application.App) error {
+	svc.prefixRoot(appInstance)
+	return nil
+}
+
+func (svc *SqlExecutorService) Destroy() error {
+	return nil
+}
+
+func (svc *SqlExecutorService) prefixRoot(appInstance *application.App) {
+	sql_executor.Bind(appInstance, &sql_executor.Simple{
+		Schema: dbSchema,
+	})
+}

+ 39 - 0
application/service/version.go

@@ -0,0 +1,39 @@
+package service
+
+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/application"
+	"git.sxidc.com/go-framework/baize/framework/core/domain"
+	"git.sxidc.com/go-framework/baize/framework/core/infrastructure"
+)
+
+var versionService = &VersionService{}
+
+type VersionService struct{}
+
+func (svc *VersionService) Init(appInstance *application.App) error {
+	svc.prefixRoot(appInstance)
+	return nil
+}
+
+func (svc *VersionService) Destroy() error {
+	return nil
+}
+
+func (svc *VersionService) prefixRoot(appInstance *application.App) {
+	prefixRootBinder := binding.NewBinder(appInstance.ChooseRouter(api.RouterPrefix, ""),
+		appInstance.Infrastructure())
+
+	binding.GetBind(prefixRootBinder, &binding.SimpleBindItem[map[string]any]{
+		Path:             "/version",
+		SendResponseFunc: response.SendMapResponse,
+		ServiceFunc: func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (map[string]any, error) {
+			return map[string]any{
+				"version": "v1.0.0",
+			}, nil
+		},
+	})
+}

+ 87 - 0
config/config.go

@@ -0,0 +1,87 @@
+package config
+
+import (
+	"fmt"
+	"git.sxidc.com/go-framework/baize/framework/core/application"
+	"git.sxidc.com/go-tools/utils/strutils"
+	"git.sxidc.com/service-supports/fslog"
+	"git.sxidc.com/service-supports/scm-sdk"
+	"gopkg.in/yaml.v3"
+	"os"
+)
+
+type Config struct {
+	ApplicationConfig application.Config
+}
+
+var conf Config
+
+func init() {
+	useSCMEnv := os.Getenv("USE_SCM")
+	if useSCMEnv == "true" {
+		initConfigFromSCM()
+	} else {
+		initConfigFromConfigFile()
+	}
+}
+
+func GetConfig() Config {
+	return conf
+}
+
+func initConfigFromSCM() {
+	scmBaseUrl := loadEnvOrPanic("SCM_BASE_URL")
+	scmNamespace := loadEnvOrPanic("SCM_NAMESPACE")
+	scmName := loadEnvOrPanic("SCM_NAME")
+
+	info, err := scm_sdk.GetCurrentConfiguration(scmBaseUrl, scmNamespace, scmName)
+	if err != nil {
+		fslog.Error(err)
+		panic(err)
+	}
+
+	applicationConfig, err := application.LoadFromYaml(info.Content)
+	if err != nil {
+		panic(err)
+	}
+
+	conf.ApplicationConfig = applicationConfig
+
+	err = yaml.Unmarshal([]byte(info.Content), &conf)
+	if err != nil {
+		panic(err)
+	}
+
+	fslog.Info("Load config from scm finish")
+}
+
+func initConfigFromConfigFile() {
+	configFilePath := os.Getenv("CONFIG_FILE_PATH")
+	applicationConfig, err := application.LoadFromYamlFile(configFilePath)
+	if err != nil {
+		panic(err)
+	}
+
+	conf.ApplicationConfig = applicationConfig
+
+	yamlBytes, err := os.ReadFile(configFilePath)
+	if err != nil {
+		panic(err)
+	}
+
+	err = yaml.Unmarshal(yamlBytes, &conf)
+	if err != nil {
+		panic(err)
+	}
+
+	fmt.Println("Load config file finish")
+}
+
+func loadEnvOrPanic(envName string) string {
+	envValue := os.Getenv(envName)
+	if strutils.IsStringEmpty(envValue) {
+		panic("请配置" + envName)
+	}
+
+	return envValue
+}

+ 5 - 0
datactl/.offline/.database/.trace.yaml

@@ -0,0 +1,5 @@
+address: 10.0.0.171
+port: "5432"
+user_name: traceability
+password: aemqJ01wKNNhr/HKWBqBE0N6TKG+6gq8/FGpcsauncU=
+database: traceability

+ 15 - 0
deployment/config/config.yaml

@@ -0,0 +1,15 @@
+api:
+  url_prefix: /ecos/api
+  port: 30665
+  log_skip_paths:
+    - /ecos/api/version
+infrastructure:
+  database:
+    operations:
+      user_name: "traceability"
+      password: "8kWaEmyHi5mfARs6"
+      address: "10.0.0.171"
+      port: "5432"
+      database: "traceability"
+      max_connections: 50
+      max_idle_connections: 10

+ 12 - 0
deployment/data_service/create_data_containers.ps1

@@ -0,0 +1,12 @@
+param (
+    [Parameter(Mandatory=$true)]
+    [string]$DatabaseName
+)
+
+Set-Location  $(Split-Path $MyInvocation.MyCommand.Path -Parent)
+
+foreach ($file in $(Get-ChildItem -Path ".\data_containers")) {
+    if ($file.GetType() -eq [System.IO.FileInfo]) {
+        datactl.exe offline database create_dc $DatabaseName -f $file.FullName
+    }
+}

+ 13 - 0
deployment/data_service/create_data_containers.sh

@@ -0,0 +1,13 @@
+#!/bin/bash
+cd "$(dirname "$0")" || exit 1
+
+if [ "$#" -ne 1 ]; then
+    echo "Usage: $0 database_name"
+    exit 1
+fi
+
+for file in ./data_containers/*; do
+	if [ -f "$file" ]; then
+		datactl offline database create_dc "$1" -f "$file"
+	fi
+done

+ 23 - 0
deployment/data_service/data_containers/configuration.yaml

@@ -0,0 +1,23 @@
+kind: DataContainer
+spec:
+  namespace: ecos
+  data_source: ecos
+  name: ecos.configurations
+  spec:
+    table_name: ecos.configurations
+    columns:
+      - name: scope
+        type: varchar(256)
+        comment: 范围
+        not_null: true
+        primary_key: true
+      - name: group
+        type: varchar(256)
+        comment: 组
+        not_null: true
+        primary_key: true
+      - name: value
+        type: varchar(256)
+        comment: 值
+        not_null: true
+        index: true

+ 41 - 0
deployment/data_service/data_containers/operate_log.yaml

@@ -0,0 +1,41 @@
+kind: DataContainer
+spec:
+  namespace: ecos
+  data_source: ecos
+  name: ecos.operate_logs
+  spec:
+    table_name: ecos.operate_logs
+    columns:
+      - name: resource
+        type: varchar(256)
+        comment: 资源名称
+        index: true
+        not_null: true
+      - name: resource_id
+        type: varchar(256)
+        comment: 资源名称
+        index: true
+        not_null: true
+      - name: operate
+        type: varchar(256)
+        comment: 操作
+        index: true
+        not_null: true
+      - name: operator_id
+        type: varchar(256)
+        comment: 操作者ID
+        index: true
+        not_null: true
+      - name: operator_name
+        type: varchar(256)
+        comment: 操作者
+        index: true
+        not_null: true
+      - name: operate_time
+        type: "timestamp with time zone"
+        comment: 操作时间
+        not_null: true
+      - name: content
+        type: text
+        comment: 日志内容
+        not_null: true

+ 57 - 0
deployment/data_service/data_containers/shop_decoration.yaml

@@ -0,0 +1,57 @@
+kind: DataContainer
+spec:
+  namespace: ecos
+  data_source: ecos
+  name: ecos.shop_decorations
+  spec:
+    table_name: ecos.shop_decorations
+    columns:
+      - name: id
+        type: "varchar(32)"
+        comment: id
+        primary_key: true
+      - name: name
+        type: "varchar(255)"
+        comment: 页面名称
+        not_null: true
+      - name: page_client_type
+        type: "varchar(32)"
+        comment: 客户端类型
+        not_null: true
+      - name: page_data
+        type: "text"
+        comment: 页面数据
+        not_null: true
+      - name: page_type
+        type: "varchar(32)"
+        comment: 页面类型
+        not_null: true
+      - name: page_show
+        type: "varchar(32)"
+        comment: 页面开关状态
+        not_null: true
+      - name: tenant_id
+        type: "varchar(32)"
+        comment: 租户ID
+        not_null: true
+        index: true
+      - name: create_user_id
+        type: "varchar(32)"
+        comment: 创建者ID
+        not_null: true
+        index: true
+      - name: last_update_user_id
+        type: "varchar(32)"
+        comment: 最后修改者ID
+        not_null: true
+        index: true
+      - name: created_time
+        type: "timestamp with time zone"
+        comment: 创建时间
+        not_null: true
+      - name: last_updated_time
+        type: "timestamp with time zone"
+        comment: 最近更新时间
+        not_null: true
+# HAC: DB TABLE SHOPDECORATION RELATION COLUMNS #
+# HAC: END DB TABLE SHOPDECORATION RELATION COLUMNS #

+ 20 - 0
deployment/data_service/data_containers/sql_executor.yaml

@@ -0,0 +1,20 @@
+kind: DataContainer
+spec:
+  namespace: ecos
+  data_source: ecos
+  name: ecos.sql_execute_logs
+  spec:
+    table_name: ecos.sql_execute_logs
+    columns:
+      - name: sql
+        type: text
+        comment: sql语句
+      - name: executor_id
+        type: varchar(32)
+        comment: 执行人ID
+      - name: executor_name
+        type: varchar(256)
+        comment: 执行人姓名
+      - name: executed_time
+        type: "timestamp with time zone"
+        comment: 执行时间

+ 12 - 0
deployment/data_service/delete_data_containers.ps1

@@ -0,0 +1,12 @@
+param (
+    [Parameter(Mandatory=$true)]
+    [string]$DatabaseName
+)
+
+Set-Location  $(Split-Path $MyInvocation.MyCommand.Path -Parent)
+
+foreach ($file in $(Get-ChildItem -Path ".\data_containers")) {
+    if ($file.GetType() -eq [System.IO.FileInfo]) {
+        datactl.exe offline database delete_dc $DatabaseName -f $file.FullName
+    }
+}

+ 13 - 0
deployment/data_service/delete_data_containers.sh

@@ -0,0 +1,13 @@
+#!/bin/bash
+cd "$(dirname "$0")" || exit 1
+
+if [ "$#" -ne 1 ]; then
+    echo "Usage: $0 database_name"
+    exit 1
+fi
+
+for file in ./data_containers/*; do
+	if [ -f "$file" ]; then
+		datactl offline database delete_dc "$1" -f "$file"
+	fi
+done

+ 97 - 0
go.mod

@@ -0,0 +1,97 @@
+module ecos
+
+go 1.24.0
+
+require (
+	git.sxidc.com/go-framework/baize v1.7.3
+	git.sxidc.com/go-tools/utils v1.5.32
+	git.sxidc.com/service-supports/fslog v0.5.9
+	git.sxidc.com/service-supports/scm-sdk v0.1.0
+	github.com/pkg/errors v0.9.1
+	github.com/stretchr/testify v1.10.0
+	github.com/vrecan/death v3.0.1+incompatible
+	gopkg.in/yaml.v3 v3.0.1
+)
+
+require (
+	git.sxidc.com/service-supports/ds-sdk v0.10.12 // indirect
+	github.com/Masterminds/goutils v1.1.1 // indirect
+	github.com/Masterminds/semver/v3 v3.2.0 // indirect
+	github.com/Masterminds/sprig/v3 v3.2.3 // indirect
+	github.com/bytedance/sonic v1.11.6 // indirect
+	github.com/bytedance/sonic/loader v0.1.1 // indirect
+	github.com/cespare/xxhash/v2 v2.2.0 // indirect
+	github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 // indirect
+	github.com/cloudwego/base64x v0.1.4 // indirect
+	github.com/cloudwego/iasm v0.2.0 // indirect
+	github.com/davecgh/go-spew v1.1.1 // indirect
+	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
+	github.com/eclipse/paho.mqtt.golang v1.4.3 // indirect
+	github.com/fatih/color v1.7.0 // indirect
+	github.com/fatih/structs v1.1.0 // indirect
+	github.com/gabriel-vasile/mimetype v1.4.3 // indirect
+	github.com/gin-contrib/sse v0.1.0 // indirect
+	github.com/gin-gonic/gin v1.10.0 // indirect
+	github.com/git-chglog/git-chglog v0.0.0-20190611050339-63a4e637021f // indirect
+	github.com/go-playground/locales v0.14.1 // indirect
+	github.com/go-playground/universal-translator v0.18.1 // indirect
+	github.com/go-playground/validator/v10 v10.20.0 // indirect
+	github.com/go-redis/redis/v7 v7.3.0 // indirect
+	github.com/go-resty/resty/v2 v2.11.0 // indirect
+	github.com/goccy/go-json v0.10.2 // indirect
+	github.com/gogo/protobuf v1.3.2 // indirect
+	github.com/golang/protobuf v1.5.4 // indirect
+	github.com/google/uuid v1.6.0 // indirect
+	github.com/gorilla/websocket v1.5.0 // indirect
+	github.com/huandu/xstrings v1.3.3 // indirect
+	github.com/iancoleman/strcase v0.3.0 // indirect
+	github.com/imdario/mergo v0.3.11 // indirect
+	github.com/jackc/pgpassfile v1.0.0 // indirect
+	github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
+	github.com/jackc/pgx/v5 v5.4.3 // indirect
+	github.com/jinzhu/inflection v1.0.0 // indirect
+	github.com/jinzhu/now v1.1.5 // indirect
+	github.com/json-iterator/go v1.1.12 // indirect
+	github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
+	github.com/klauspost/cpuid/v2 v2.2.7 // indirect
+	github.com/leodido/go-urn v1.4.0 // indirect
+	github.com/mattn/go-colorable v0.1.2 // indirect
+	github.com/mattn/go-isatty v0.0.20 // indirect
+	github.com/mattn/goveralls v0.0.2 // indirect
+	github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
+	github.com/mitchellh/copystructure v1.0.0 // indirect
+	github.com/mitchellh/reflectwalk v1.0.0 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/mwitkow/go-proto-validators v0.3.2 // indirect
+	github.com/pelletier/go-toml/v2 v2.2.2 // indirect
+	github.com/pmezard/go-difflib v1.0.0 // indirect
+	github.com/redis/go-redis/v9 v9.4.0 // indirect
+	github.com/robinjoseph08/redisqueue/v2 v2.1.0 // indirect
+	github.com/satori/go.uuid v1.2.0 // indirect
+	github.com/shopspring/decimal v1.2.0 // indirect
+	github.com/smartystreets/goconvey v1.8.1 // indirect
+	github.com/spf13/cast v1.3.1 // indirect
+	github.com/tsuyoshiwada/go-gitcmd v0.0.0-20180205145712-5f1f5f9475df // indirect
+	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
+	github.com/ugorji/go/codec v1.2.12 // indirect
+	github.com/urfave/cli v1.20.0 // indirect
+	go.uber.org/multierr v1.11.0 // indirect
+	go.uber.org/zap v1.27.0 // indirect
+	golang.org/x/arch v0.8.0 // indirect
+	golang.org/x/crypto v0.23.0 // indirect
+	golang.org/x/net v0.25.0 // indirect
+	golang.org/x/sync v0.6.0 // indirect
+	golang.org/x/sys v0.20.0 // indirect
+	golang.org/x/text v0.15.0 // indirect
+	golang.org/x/tools v0.7.0 // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect
+	google.golang.org/grpc v1.64.0 // indirect
+	google.golang.org/protobuf v1.34.1 // indirect
+	gopkg.in/AlecAivazis/survey.v1 v1.8.5 // indirect
+	gopkg.in/kyokomi/emoji.v1 v1.5.1 // indirect
+	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
+	gopkg.in/yaml.v2 v2.4.0 // indirect
+	gorm.io/driver/postgres v1.5.7 // indirect
+	gorm.io/gorm v1.25.10 // indirect
+)

+ 340 - 0
go.sum

@@ -0,0 +1,340 @@
+git.sxidc.com/go-framework/baize v1.7.3 h1:k+hHPciyOIkDGz+izH7/LebtxJfrzVPN2U+7LplUi0Y=
+git.sxidc.com/go-framework/baize v1.7.3/go.mod h1:cZ7OItBfrCv5TSWNmkF5iaCRmBly/6XPnv020TyVUVA=
+git.sxidc.com/go-tools/utils v1.5.32 h1:FapJ86BJ8UfH12t9jP+9UOaoPX9ZtoN41HU8oFX0/A0=
+git.sxidc.com/go-tools/utils v1.5.32/go.mod h1:uTDb6QK5JZzK5+Fzsfeng7TwmnRDZiTY6JLYxIX94Qw=
+git.sxidc.com/service-supports/ds-sdk v0.10.12 h1:xg8uuSBPMVcPXXx7snPhZithgqxfJSJ8AZB+f1smE1o=
+git.sxidc.com/service-supports/ds-sdk v0.10.12/go.mod h1:QS5FgT3fyPbDl4ak6BO5IF7X4B6Z2uQWpRPskYb/oto=
+git.sxidc.com/service-supports/fslog v0.5.9 h1:q2XIK2o/fk/qmByy4x5kKLC+k7kolT5LrXHcWRSffXQ=
+git.sxidc.com/service-supports/fslog v0.5.9/go.mod h1:/m03ATmmOle75qtEgvEw8a1+Dcg6iHp08M1bGFXJTBU=
+git.sxidc.com/service-supports/scm-sdk v0.1.0 h1:198qs/XxffOrHioKEWXyPfsQLoO3E8Ifj4idOWJxIe0=
+git.sxidc.com/service-supports/scm-sdk v0.1.0/go.mod h1:F0DLFok92zElZZRxJujSk6KmRoVGN8bkrbXFdq19uwI=
+github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
+github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
+github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
+github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
+github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
+github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
+github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
+github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
+github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
+github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
+github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
+github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
+github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
+github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
+github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
+github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
+github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
+github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 h1:kHaBemcxl8o/pQ5VM1c8PVE1PubbNx3mjUr09OqWGCs=
+github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575/go.mod h1:9d6lWj8KzO/fd/NrVaLscBKmPigpZpn5YawRPw+e3Yo=
+github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
+github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
+github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
+github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
+github.com/eclipse/paho.mqtt.golang v1.4.3 h1:2kwcUGn8seMUfWndX0hGbvH8r7crgcJguQNCyp70xik=
+github.com/eclipse/paho.mqtt.golang v1.4.3/go.mod h1:CSYvoAlsMkhYOXh/oKyxa8EcBci6dVkLCbo5tTC1RIE=
+github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
+github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
+github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
+github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
+github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
+github.com/git-chglog/git-chglog v0.0.0-20190611050339-63a4e637021f h1:8l4Aw3Jmx0pLKYMkY+1b6yBPgE+rzRtA5T3vqFyI2Z8=
+github.com/git-chglog/git-chglog v0.0.0-20190611050339-63a4e637021f/go.mod h1:Dcsy1kii/xFyNad5JqY/d0GO5mu91sungp5xotbm3Yk=
+github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
+github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
+github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
+github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
+github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
+github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
+github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
+github.com/go-redis/redis/v7 v7.3.0 h1:3oHqd0W7f/VLKBxeYTEpqdMUsmMectngjM9OtoRoIgg=
+github.com/go-redis/redis/v7 v7.3.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg=
+github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8=
+github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
+github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
+github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
+github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
+github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
+github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
+github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
+github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=
+github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
+github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
+github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
+github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
+github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
+github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
+github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
+github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
+github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
+github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
+github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
+github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
+github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
+github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
+github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
+github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
+github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
+github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
+github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
+github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/goveralls v0.0.2 h1:7eJB6EqsPhRVxvwEXGnqdO2sJI0PTsrWoTMXEk9/OQc=
+github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
+github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
+github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
+github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
+github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
+github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
+github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/mwitkow/go-proto-validators v0.3.2 h1:qRlmpTzm2pstMKKzTdvwPCF5QfBNURSlAgN/R+qbKos=
+github.com/mwitkow/go-proto-validators v0.3.2/go.mod h1:ej0Qp0qMgHN/KtDyUt+Q1/tA7a5VarXUOUxD+oeD30w=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
+github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
+github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
+github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
+github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
+github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/redis/go-redis/v9 v9.4.0 h1:Yzoz33UZw9I/mFhx4MNrB6Fk+XHO1VukNcCa1+lwyKk=
+github.com/redis/go-redis/v9 v9.4.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
+github.com/robinjoseph08/redisqueue/v2 v2.1.0 h1:GactHlrxS8YSCJc4CbP1KbTObo14pieNmNWSUlquTGI=
+github.com/robinjoseph08/redisqueue/v2 v2.1.0/go.mod h1:fiNYBqIF/DqZxKvO6faLB6nkBtfJucuM+rDbFhZG1vs=
+github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
+github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
+github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
+github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
+github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
+github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
+github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY=
+github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec=
+github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
+github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60=
+github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
+github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
+github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/tsuyoshiwada/go-gitcmd v0.0.0-20180205145712-5f1f5f9475df h1:Y2l28Jr3vOEeYtxfVbMtVfOdAwuUqWaP9fvNKiBVeXY=
+github.com/tsuyoshiwada/go-gitcmd v0.0.0-20180205145712-5f1f5f9475df/go.mod h1:pnyouUty/nBr/zm3GYwTIt+qFTLWbdjeLjZmJdzJOu8=
+github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
+github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
+github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
+github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
+github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
+github.com/vrecan/death v3.0.1+incompatible h1:hYRRqrdyoUAbymk2KJ8tNHmZFKcVeThRUySCqwC5Itg=
+github.com/vrecan/death v3.0.1+incompatible/go.mod h1:ektTae4lwvcXJ7pytrLb2N0w7mwhzmu+f5vRHYzy33E=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
+go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
+golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
+golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
+golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
+golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
+golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
+golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
+golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
+golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
+google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
+google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
+google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
+google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+gopkg.in/AlecAivazis/survey.v1 v1.8.5 h1:QoEEmn/d5BbuPIL2qvXwzJdttFFhRQFkaq+tEKb7SMI=
+gopkg.in/AlecAivazis/survey.v1 v1.8.5/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/kyokomi/emoji.v1 v1.5.1 h1:beetH5mWDMzFznJ+Qzd5KVHp79YKhVUMcdO8LpRLeGw=
+gopkg.in/kyokomi/emoji.v1 v1.5.1/go.mod h1:N9AZ6hi1jHOPn34PsbpufQZUcKftSD7WgS2pgpmH4Lg=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM=
+gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA=
+gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
+gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
+nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

+ 30 - 0
main.go

@@ -0,0 +1,30 @@
+package main
+
+import (
+	"ecos/application"
+	DEATH "gith
+	DEATH "github.com/vrecan/death"
+	"ecos/application"
+)
+
+func main() {
+	application.NewApp()
+	defer application.DestroyApp()
+
+	go func() {
+		err := application.Start()
+		if err != nil {
+			panic(err)
+		}
+	}()
+
+	defer func() {
+		err := application.Finish()
+		if err != nil {
+			panic(err)
+		}
+	}()
+
+	death := DEATH.NewDeath(syscall.SIGINT, syscall.SIGTERM)
+	_ = death.WaitForDeath()
+}

+ 208 - 0
test/shop_decoration_test.go

@@ -0,0 +1,208 @@
+package test
+
+import (
+	"ecos/application/domain/shop_decoration"
+	"git.sxidc.com/go-framework/baize/framework/core/api/request"
+	"git.sxidc.com/go-framework/baize/framework/core/api/response"
+	"git.sxidc.com/go-tools/utils/strutils"
+	"net/http"
+	"testing"
+)
+
+func TestShopDecoration(t *testing.T) {
+	Init()
+	defer Destroy()
+
+	var shopDecorationID string
+	var totalCount int64
+	shopDecorationInfo := new(shop_decoration.Info)
+	shopDecorationInfos := make([]shop_decoration.Info, 0)
+	tenantID := strutils.SimpleUUID()
+	createUserID := strutils.SimpleUUID()
+	updateUserID := strutils.SimpleUUID()
+	deleteUserID := strutils.SimpleUUID()
+	operatorUserName := strutils.SimpleUUID()
+	name := strutils.SimpleUUID()
+	pageClientType := strutils.SimpleUUID()
+	pageData := strutils.SimpleUUID()
+	pageType := strutils.SimpleUUID()
+	pageShow := strutils.SimpleUUID()
+	newName := strutils.SimpleUUID()
+	newPageClientType := strutils.SimpleUUID()
+	newPageData := strutils.SimpleUUID()
+	newPageType := strutils.SimpleUUID()
+	newPageShow := strutils.SimpleUUID()
+
+	NewToolKit(t).CreateShopDecoration(tenantID, name, pageClientType, pageData, pageType, pageShow, createUserID, operatorUserName, &shopDecorationID).
+		GetShopDecoration(tenantID, shopDecorationID, shopDecorationInfo).
+		AssertEqual(tenantID, shopDecorationInfo.TenantID, "店铺装修列表租户ID不一致").
+		AssertEqual(shopDecorationID, shopDecorationInfo.ID, "店铺装修列表ID不一致").
+		AssertEqual(name, shopDecorationInfo.Name, "店铺装修列表页面名称不一致").
+		AssertEqual(pageClientType, shopDecorationInfo.PageClientType, "店铺装修列表客户端类型不一致").
+		AssertEqual(pageData, shopDecorationInfo.PageData, "店铺装修列表页面数据不一致").
+		AssertEqual(pageType, shopDecorationInfo.PageType, "店铺装修列表页面类型不一致").
+		AssertEqual(pageShow, shopDecorationInfo.PageShow, "店铺装修列表页面开关状态不一致").
+		AssertEqual(createUserID, shopDecorationInfo.CreateUserID, "创建用户ID不一致").
+		AssertEqual(createUserID, shopDecorationInfo.LastUpdateUserID, "最近更新用户ID不一致").
+		AssertNotEmpty(shopDecorationInfo.CreatedTime, "创建时间为空").
+		AssertNotEmpty(shopDecorationInfo.LastUpdatedTime, "最近更新时间为空").
+		GetShopDecorations(tenantID, name, pageClientType, pageData, pageType, pageShow, "1", "1", &shopDecorationInfos, &totalCount).
+		AssertEqual(int(totalCount), len(shopDecorationInfos), "总数不一致").
+		AssertEqual(tenantID, shopDecorationInfos[0].TenantID, "店铺装修列表租户ID不一致").
+		AssertEqual(shopDecorationID, shopDecorationInfos[0].ID, "店铺装修列表ID不一致").
+		AssertEqual(name, shopDecorationInfos[0].Name, "店铺装修列表页面名称不一致").
+		AssertEqual(pageClientType, shopDecorationInfos[0].PageClientType, "店铺装修列表客户端类型不一致").
+		AssertEqual(pageData, shopDecorationInfos[0].PageData, "店铺装修列表页面数据不一致").
+		AssertEqual(pageType, shopDecorationInfos[0].PageType, "店铺装修列表页面类型不一致").
+		AssertEqual(pageShow, shopDecorationInfos[0].PageShow, "店铺装修列表页面开关状态不一致").
+		AssertEqual(createUserID, shopDecorationInfos[0].CreateUserID, "创建用户ID不一致").
+		AssertEqual(createUserID, shopDecorationInfos[0].LastUpdateUserID, "最近更新用户ID不一致").
+		AssertNotEmpty(shopDecorationInfos[0].CreatedTime, "创建时间为空").
+		AssertNotEmpty(shopDecorationInfos[0].LastUpdatedTime, "最近更新时间为空").
+		GetShopDecorations(tenantID, name, pageClientType, pageData, pageType, pageShow, "0", "0", &shopDecorationInfos, &totalCount).
+		AssertEqual(int(totalCount), len(shopDecorationInfos), "总数不一致").
+		AssertEqual(1, len(shopDecorationInfos), "店铺装修列表数应当为1").
+		AssertEqual(tenantID, shopDecorationInfos[0].TenantID, "店铺装修列表租户ID不一致").
+		AssertEqual(shopDecorationID, shopDecorationInfos[0].ID, "店铺装修列表ID不一致").
+		AssertEqual(name, shopDecorationInfos[0].Name, "店铺装修列表页面名称不一致").
+		AssertEqual(pageClientType, shopDecorationInfos[0].PageClientType, "店铺装修列表客户端类型不一致").
+		AssertEqual(pageData, shopDecorationInfos[0].PageData, "店铺装修列表页面数据不一致").
+		AssertEqual(pageType, shopDecorationInfos[0].PageType, "店铺装修列表页面类型不一致").
+		AssertEqual(pageShow, shopDecorationInfos[0].PageShow, "店铺装修列表页面开关状态不一致").
+		AssertEqual(createUserID, shopDecorationInfos[0].CreateUserID, "创建用户ID不一致").
+		AssertEqual(createUserID, shopDecorationInfos[0].LastUpdateUserID, "最近更新用户ID不一致").
+		AssertNotEmpty(shopDecorationInfos[0].CreatedTime, "创建时间为空").
+		AssertNotEmpty(shopDecorationInfos[0].LastUpdatedTime, "最近更新时间为空").
+		UpdateShopDecoration(shopDecorationID, newName, newPageClientType, newPageData, newPageType, newPageShow, updateUserID, operatorUserName).
+		GetShopDecorations(tenantID, newName, newPageClientType, newPageData, newPageType, newPageShow, "1", "1", &shopDecorationInfos, &totalCount).
+		AssertEqual(int(totalCount), len(shopDecorationInfos), "总数不一致").
+		AssertEqual(tenantID, shopDecorationInfos[0].TenantID, "店铺装修列表租户ID不一致").
+		AssertEqual(shopDecorationID, shopDecorationInfos[0].ID, "店铺装修列表ID不一致").
+		AssertEqual(newName, shopDecorationInfos[0].Name, "店铺装修列表页面名称不一致").
+		AssertEqual(newPageClientType, shopDecorationInfos[0].PageClientType, "店铺装修列表客户端类型不一致").
+		AssertEqual(newPageData, shopDecorationInfos[0].PageData, "店铺装修列表页面数据不一致").
+		AssertEqual(newPageType, shopDecorationInfos[0].PageType, "店铺装修列表页面类型不一致").
+		AssertEqual(newPageShow, shopDecorationInfos[0].PageShow, "店铺装修列表页面开关状态不一致").
+		AssertEqual(createUserID, shopDecorationInfos[0].CreateUserID, "创建用户ID不一致").
+		AssertEqual(updateUserID, shopDecorationInfos[0].LastUpdateUserID, "最近更新用户ID不一致").
+		AssertNotEmpty(shopDecorationInfos[0].CreatedTime, "创建时间为空").
+		AssertNotEmpty(shopDecorationInfos[0].LastUpdatedTime, "最近更新时间为空").
+		DeleteShopDecoration(shopDecorationID, deleteUserID, operatorUserName).
+		GetShopDecorations(tenantID, newName, newPageClientType, newPageData, newPageType, newPageShow, "1", "1", &shopDecorationInfos, &totalCount).
+		AssertEqual(int(totalCount), len(shopDecorationInfos), "总数不一致").
+		AssertEqual(0, len(shopDecorationInfos), "删除店铺装修列表失败")
+}
+
+/* HAC: TEST RELATION FUNCTIONS */
+/* HAC: END TEST RELATION FUNCTIONS */
+
+func (toolKit *ToolKit) CreateShopDecoration(tenantID string, name string, pageClientType string, pageData string, pageType string, pageShow string, createUserID string, operatorUserName string, shopDecorationID *string) *ToolKit {
+	idResponse := new(response.IDResponse)
+
+	toolKit.SetHeader("Content-Type", "application/json").
+		SetJsonBody(&shop_decoration.CreateShopDecorationJsonBody{
+			Name: name, PageClientType: pageClientType, PageData: pageData, PageType: pageType, PageShow: pageShow,
+			TenantIDJsonBody:         request.TenantIDJsonBody{TenantID: tenantID},
+			CreateUserIDJsonBody:     request.CreateUserIDJsonBody{CreateUserID: createUserID},
+			OperatorUserNameJsonBody: request.OperatorUserNameJsonBody{OperatorUserName: operatorUserName},
+		}).
+		SetJsonResponse(idResponse).
+		Request("/ecos/api/v1/shopDecoration/create", http.MethodPost).
+		AssertStatusCode(http.StatusOK).
+		AssertEqual(true, idResponse.Success, idResponse.Msg).
+		AssertNotEmpty(idResponse.ID, "店铺装修列表ID为空")
+
+	if shopDecorationID != nil {
+		*shopDecorationID = idResponse.ID
+	}
+
+	return toolKit
+}
+
+func (toolKit *ToolKit) DeleteShopDecoration(id string, deleteUserID string, operatorUserName string) *ToolKit {
+	msgResponse := new(response.MsgResponse)
+
+	toolKit.SetHeader("Content-Type", "application/json").
+		SetJsonResponse(msgResponse).
+		SetQueryParams("id", id).
+		SetQueryParams("deleteUserId", deleteUserID).
+		SetQueryParams("operatorUserName", operatorUserName).
+		Request("/ecos/api/v1/shopDecoration/delete", http.MethodDelete).
+		AssertStatusCode(http.StatusOK).
+		AssertEqual(true, msgResponse.Success, msgResponse.Msg)
+
+	return toolKit
+}
+
+func (toolKit *ToolKit) UpdateShopDecoration(id string, name string, pageClientType string, pageData string, pageType string, pageShow string, updateUserID string, operatorUserName string) *ToolKit {
+	msgResponse := new(response.MsgResponse)
+
+	toolKit.SetHeader("Content-Type", "application/json").
+		SetJsonBody(&shop_decoration.UpdateShopDecorationJsonBody{
+			IDJsonBody:               request.IDJsonBody{ID: id},
+			Name:                     name,
+			PageClientType:           pageClientType,
+			PageData:                 pageData,
+			PageType:                 pageType,
+			PageShow:                 pageShow,
+			UpdateUserIDJsonBody:     request.UpdateUserIDJsonBody{UpdateUserID: updateUserID},
+			OperatorUserNameJsonBody: request.OperatorUserNameJsonBody{OperatorUserName: operatorUserName},
+		}).
+		SetJsonResponse(msgResponse).
+		Request("/ecos/api/v1/shopDecoration/update", http.MethodPut).
+		AssertStatusCode(http.StatusOK).
+		AssertEqual(true, msgResponse.Success, msgResponse.Msg)
+
+	return toolKit
+}
+
+func (toolKit *ToolKit) GetShopDecorations(tenantID string, name string, pageClientType string, pageData string, pageType string, pageShow string, pageNo string, pageSize string, retInfos *[]shop_decoration.Info, retTotalCount *int64) *ToolKit {
+	infosResponse := new(response.InfosResponse[shop_decoration.Info])
+
+	toolKit.SetHeader("Content-Type", "application/json").
+		SetJsonResponse(infosResponse).
+		SetQueryParams("tenantId", tenantID).
+		SetQueryParams("name", name).
+		SetQueryParams("pageClientType", pageClientType).
+		SetQueryParams("pageData", pageData).
+		SetQueryParams("pageType", pageType).
+		SetQueryParams("pageShow", pageShow).
+		SetQueryParams("pageNo", pageNo).
+		SetQueryParams("pageSize", pageSize).
+		Request("/ecos/api/v1/shopDecoration/query", http.MethodGet).
+		AssertStatusCode(http.StatusOK).
+		AssertEqual(true, infosResponse.Success, infosResponse.Msg)
+
+	if retInfos != nil {
+		*retInfos = make([]shop_decoration.Info, 0)
+		*retInfos = append(*retInfos, infosResponse.Infos...)
+	}
+
+	if retTotalCount != nil {
+		*retTotalCount = infosResponse.TotalCount
+	}
+
+	return toolKit
+}
+
+func (toolKit *ToolKit) GetShopDecoration(tenantID string, id string, retInfo *shop_decoration.Info) *ToolKit {
+	infoResponse := new(response.InfoResponse[*shop_decoration.Info])
+
+	toolKit.SetHeader("Content-Type", "application/json").
+		SetJsonResponse(infoResponse).
+		SetQueryParams("tenantId", tenantID).
+		SetQueryParams("id", id).
+		Request("/ecos/api/v1/shopDecoration/get", http.MethodGet).
+		AssertStatusCode(http.StatusOK).
+		AssertEqual(true, infoResponse.Success, infoResponse.Msg)
+
+	if retInfo != nil {
+		*retInfo = shop_decoration.Info{}
+		*retInfo = *infoResponse.Info
+	}
+
+	return toolKit
+}
+
+/* HAC: TEST RELATION METHODS */
+/* HAC: END TEST RELATION METHODS */

+ 186 - 0
test/tool_kit.go

@@ -0,0 +1,186 @@
+package test
+
+import (
+	"bytes"
+	"ecos/application"
+	"encoding/json"
+	"git.sxidc.com/go-tools/utils/strutils"
+	"github.com/stretchr/testify/assert"
+	"io"
+	"net/http"
+	"net/http/httptest"
+	"reflect"
+	"testing"
+	"time"
+)
+
+type ToolKit struct {
+	t *testing.T
+
+	body         io.Reader
+	header       map[string]string
+	queryParams  map[string]string
+	jsonResponse interface{}
+	token        string
+
+	responseRecorder *httptest.ResponseRecorder
+}
+
+func Init() {
+	application.NewApp()
+
+	go func() {
+		err := application.Start()
+		if err != nil {
+			panic(err)
+		}
+	}()
+
+	time.Sleep(100 * time.Millisecond)
+}
+
+func Destroy() {
+	err := application.Finish()
+	if err != nil {
+		panic(err)
+	}
+
+	application.DestroyApp()
+}
+
+func NewToolKit(t *testing.T) *ToolKit {
+	return &ToolKit{
+		t:           t,
+		header:      make(map[string]string),
+		queryParams: make(map[string]string),
+	}
+}
+
+func (toolKit *ToolKit) SetHeader(key string, value string) *ToolKit {
+	toolKit.header[key] = value
+	return toolKit
+}
+
+func (toolKit *ToolKit) SetBody(body *bytes.Buffer) *ToolKit {
+	toolKit.body = body
+	return toolKit
+}
+
+func (toolKit *ToolKit) SetQueryParams(key string, value string) *ToolKit {
+	toolKit.queryParams[key] = value
+	return toolKit
+}
+
+func (toolKit *ToolKit) SetJsonBody(body interface{}) *ToolKit {
+	jsonBody, err := json.Marshal(body)
+	if err != nil {
+		toolKit.t.Fatal("转换JSON失败")
+	}
+
+	toolKit.body = bytes.NewBuffer(jsonBody)
+
+	return toolKit
+}
+
+func (toolKit *ToolKit) SetJsonResponse(response interface{}) *ToolKit {
+	if response == nil {
+		toolKit.jsonResponse = nil
+		return toolKit
+	}
+
+	responseValue := reflect.ValueOf(response)
+	if responseValue.Kind() != reflect.Ptr {
+		toolKit.t.Fatal("JsonResponse应该传递指针类型")
+	}
+
+	toolKit.jsonResponse = response
+
+	return toolKit
+}
+
+func (toolKit *ToolKit) SetToken(token string) *ToolKit {
+	toolKit.token = token
+	return toolKit
+}
+
+func (toolKit *ToolKit) Request(url string, method string) *ToolKit {
+	if len(toolKit.queryParams) != 0 {
+		url = url + "?"
+		for key, value := range toolKit.queryParams {
+			url = url + key + "=" + value + "&"
+		}
+
+		url = url[:len(url)-1]
+
+		toolKit.queryParams = make(map[string]string)
+	}
+
+	request, err := http.NewRequest(method, url, toolKit.body)
+	if err != nil {
+		toolKit.t.Fatal("创建请求失败", err)
+	}
+
+	if len(toolKit.header) != 0 {
+		for key, value := range toolKit.header {
+			request.Header.Add(key, value)
+		}
+
+		toolKit.header = make(map[string]string)
+	}
+
+	if !strutils.IsStringEmpty(toolKit.token) {
+		request.Header.Add("Authorization", toolKit.token)
+	}
+
+	toolKit.responseRecorder = httptest.NewRecorder()
+	application.ServerHttpForTest(toolKit.responseRecorder, request)
+
+	if toolKit.responseRecorder.Code == http.StatusOK && toolKit.jsonResponse != nil {
+		responseBody, err := io.ReadAll(toolKit.responseRecorder.Body)
+		if err != nil {
+			toolKit.t.Fatal("读取响应Body失败")
+		}
+
+		err = json.Unmarshal(responseBody, toolKit.jsonResponse)
+		if err != nil {
+			toolKit.t.Fatal("转换Response失败")
+		}
+	}
+
+	return toolKit
+}
+
+func (toolKit *ToolKit) AssertStatusCode(code int) *ToolKit {
+	assert.Equal(toolKit.t, code, toolKit.responseRecorder.Code)
+	return toolKit
+}
+
+func (toolKit *ToolKit) AssertBodyEqual(body string) *ToolKit {
+	assert.Equal(toolKit.t, body, toolKit.responseRecorder.Body.String())
+	return toolKit
+}
+
+func (toolKit *ToolKit) AssertEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) *ToolKit {
+	assert.Equal(toolKit.t, expected, actual, msgAndArgs)
+	return toolKit
+}
+
+func (toolKit *ToolKit) AssertNotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) *ToolKit {
+	assert.NotEqual(toolKit.t, expected, actual, msgAndArgs)
+	return toolKit
+}
+
+func (toolKit *ToolKit) AssertNotEmpty(object interface{}, msgAndArgs ...interface{}) *ToolKit {
+	assert.NotEmpty(toolKit.t, object, msgAndArgs)
+	return toolKit
+}
+
+func (toolKit *ToolKit) AssertGreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) *ToolKit {
+	assert.GreaterOrEqual(toolKit.t, e1, e2, msgAndArgs)
+	return toolKit
+}
+
+func (toolKit *ToolKit) AssertZero(e1 interface{}, msgAndArgs ...interface{}) *ToolKit {
+	assert.Zero(toolKit.t, e1, msgAndArgs)
+	return toolKit
+}

+ 20 - 0
test/version_test.go

@@ -0,0 +1,20 @@
+package test
+
+import (
+	"net/http"
+	"testing"
+)
+
+func TestVersion(t *testing.T) {
+	Init()
+	defer Destroy()
+
+	versionResponse := &struct {
+		Version string `json:"version"`
+	}{}
+
+	NewToolKit(t).SetJsonResponse(versionResponse).
+		Request("/ecos/api/version", http.MethodGet).
+		AssertStatusCode(http.StatusOK).
+		AssertEqual(versionResponse.Version, "v1.0.0")
+}