From 9ac5c16aa34d6fbdf0fb1ea3ac1133f5339a4f3a Mon Sep 17 00:00:00 2001 From: Nikitin Aleksandr Date: Mon, 12 Feb 2024 15:25:44 +0300 Subject: [PATCH] =?UTF-8?q?=D1=81=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20NEED=5FC?= =?UTF-8?q?REATE=5FUPDATE=5FEVERY=5FCOLUMN?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/templates/api/service.proto_ | 26 +++ bin/templates/configs_/settings.txt | 5 +- .../entities/model_table_update.go_ | 6 + internal/config/config.go | 2 + internal/constants/constants.go | 1 + internal/create_files/create_files.go | 47 ++++++ internal/create_files/create_files_columns.go | 9 ++ .../create_files/model_tables/model_tables.go | 153 ++++++++++++++++++ internal/create_files/protobuf/protobuf.go | 98 +++++++++++ .../create_files/protobuf/protobuf_test.go | 14 ++ 10 files changed, 360 insertions(+), 1 deletion(-) create mode 100644 bin/templates/pkg/object_model/entities/model_table_update.go_ diff --git a/bin/templates/api/service.proto_ b/bin/templates/api/service.proto_ index 9e7943d..9b84767 100644 --- a/bin/templates/api/service.proto_ +++ b/bin/templates/api/service.proto_ @@ -9,6 +9,8 @@ package grpc; option go_package = "./grpc_proto"; +import "google/protobuf/timestamp.proto"; + // sync_service - сервис обмена с Базой данных service Sync_service { } @@ -76,3 +78,27 @@ message ResponseFloat64 { message ResponseEmpty { } +// RequestDate - параметры запроса на сервер +message RequestDate { + uint32 VersionModel= 1; //версия структуры модели + google.protobuf.Timestamp Date = 2; // строка поиска +} + +// RequestFloat64 - параметры запроса на сервер, передаётся float64 +message RequestFloat64 { + uint32 VersionModel= 1; //версия структуры модели + double Float64 = 2; // строка поиска +} + +// RequestFloat32 - параметры запроса на сервер, передаётся float32 +message RequestFloat32 { + uint32 VersionModel= 1; //версия структуры модели + float Float32 = 2; // строка поиска +} + +// RequestInt32 - параметры запроса на сервер, передаётся int32 +message RequestInt32 { + uint32 VersionModel= 1; //версия структуры модели + int32 Int32 = 2; // строка поиска +} + diff --git a/bin/templates/configs_/settings.txt b/bin/templates/configs_/settings.txt index 5938664..5a6f439 100644 --- a/bin/templates/configs_/settings.txt +++ b/bin/templates/configs_/settings.txt @@ -167,4 +167,7 @@ READY_ALIAS_FILENAME="alias.go" TEMPLATES_CRUD_FILENAME="crud_tables_rapira.go_" #TEMPLATES_CRUD_TEST_FILENAME - short filename of "crud_tables_test.go_" file -TEMPLATES_CRUD_TEST_FILENAME="crud_tables_rapira_test.go_" \ No newline at end of file +TEMPLATES_CRUD_TEST_FILENAME="crud_tables_rapira_test.go_" + +#NEED_CREATE_UPDATE_EVERY_COLUMN - fill true if you want create Update_ColumnName() function for every column +NEED_CREATE_UPDATE_EVERY_COLUMN=true \ No newline at end of file diff --git a/bin/templates/pkg/object_model/entities/model_table_update.go_ b/bin/templates/pkg/object_model/entities/model_table_update.go_ new file mode 100644 index 0000000..ea688eb --- /dev/null +++ b/bin/templates/pkg/object_model/entities/model_table_update.go_ @@ -0,0 +1,6 @@ +package lawsuit_status_types + +import ( + "gitlab.aescorp.ru/dsp_dev/claim/sync_service/pkg/db/constants" + ) + diff --git a/internal/config/config.go b/internal/config/config.go index 4415b05..ab99711 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -68,6 +68,7 @@ type SettingsINI struct { TEXT_MODULE_GENERATED string PREFIX_TABLE string READY_ALIAS_FILENAME string + NEED_CREATE_UPDATE_EVERY_COLUMN bool } // FillSettings загружает переменные окружения в структуру из переменных окружения @@ -177,6 +178,7 @@ func FillSettings() { Settings.TEMPLATES_CRUD_TEST_FILENAME = os.Getenv("TEMPLATES_CRUD_TEST_FILENAME") Settings.TEMPLATES_ALIAS_FILENAME = os.Getenv("TEMPLATES_ALIAS_FILENAME") Settings.READY_ALIAS_FILENAME = os.Getenv("READY_ALIAS_FILENAME") + Settings.NEED_CREATE_UPDATE_EVERY_COLUMN = BoolFromString(os.Getenv("NEED_CREATE_UPDATE_EVERY_COLUMN")) } diff --git a/internal/constants/constants.go b/internal/constants/constants.go index ea6268f..851aa2b 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -46,3 +46,4 @@ const STARTER_TABLES_PREFIX = "crud_starter_" const CRUD_TABLES_FREFIX = "crud_" const MODEL_TABLE_MANUAL_FILENAME = "model_table_manual.go_" +const MODEL_TABLE_UPDATE_FILENAME = "model_table_update.go_" diff --git a/internal/create_files/create_files.go b/internal/create_files/create_files.go index 978dafd..f2b9c8e 100644 --- a/internal/create_files/create_files.go +++ b/internal/create_files/create_files.go @@ -842,3 +842,50 @@ func DeleteLastUnderline(s string) string { return Otvet } + +// FindLastGoodPos - возвращает позицию последнего нахождения, с новой строки +func FindLastGoodPos(s, TextFind string) int { + Otvet := -1 + pos1 := strings.LastIndex(s, TextFind) + if pos1 < 0 { + return Otvet + } + pos2 := strings.Index(s[pos1:], "\n") + if pos2 < 0 { + return Otvet + } + Otvet = pos1 + pos2 + 1 + + return Otvet +} + +// AddInterfaceFunction - добавляет функцию в интерфейс +func AddInterfaceFunction(s, TextAdd string) string { + Otvet := s + + //Проверим такая функция уже есть + pos1 := strings.Index(Otvet, TextAdd) + if pos1 >= 0 { + return Otvet + } + + //найдём начало интефейса + sFind := " interface {" + pos1 = FindLastGoodPos(Otvet, sFind) + if pos1 < 0 { + log.Error("FindLastGoodPos() error: not found: ", sFind) + return Otvet + } + + s2 := Otvet[pos1:] + pos2 := strings.Index(s2, "\n}") + if pos2 < 0 { + log.Error("FindLastGoodPos() error: not found: \\n") + return Otvet + } + PosStart := pos1 + pos2 + + Otvet = Otvet[:PosStart] + TextAdd + Otvet[PosStart:] + + return Otvet +} diff --git a/internal/create_files/create_files_columns.go b/internal/create_files/create_files_columns.go index 4f3f0d5..3f82eaf 100644 --- a/internal/create_files/create_files_columns.go +++ b/internal/create_files/create_files_columns.go @@ -306,3 +306,12 @@ func Is_Column_ExtLinksStruct(Column1 *types.Column) bool { return Otvet } + +// Is_Common_Сolumn - возвращает true если это общая колонка: table_name_id, table_row_idб is_group, parent_id, name или description, ext_id, created_at, modified_at, deleted_at, id +func Is_Common_Сolumn(Column1 *types.Column) bool { + Otvet := false + + Otvet = Is_Column_CommonStruct(Column1) || Is_Column_NameStruct(Column1) || Is_Column_GroupsStruct(Column1) || Is_Column_ExtLinksStruct(Column1) + + return Otvet +} diff --git a/internal/create_files/model_tables/model_tables.go b/internal/create_files/model_tables/model_tables.go index ce7f013..8f348c1 100644 --- a/internal/create_files/model_tables/model_tables.go +++ b/internal/create_files/model_tables/model_tables.go @@ -25,6 +25,14 @@ func CreateAllFiles(MapAll map[string]*types.Table) error { log.Error("CreateFiles() table: ", table1.Name, " error: ", err) return err } + + if config.Settings.NEED_CREATE_UPDATE_EVERY_COLUMN == true { + err = CreateFilesUpdateEveryColumn(table1) + if err != nil { + log.Error("CreateFiles() table: ", table1.Name, " error: ", err) + return err + } + } } return err @@ -172,6 +180,11 @@ func CreateFilesModel_crud(Table1 *types.Table, DirTemplatesModel, DirReadyModel TextModel = DeleteFromInterfaceFind_ByExtID(TextModel, Table1) } + // + if config.Settings.NEED_CREATE_UPDATE_EVERY_COLUMN == true { + TextModel = AddInterfaceUpdateEveryColumn(TextModel, Table1) + } + //создание текста TextModel = strings.ReplaceAll(TextModel, config.Settings.TEXT_TEMPLATE_MODEL, ModelName) TextModel = strings.ReplaceAll(TextModel, config.Settings.TEXT_TEMPLATE_TABLENAME, Table1.Name) @@ -507,3 +520,143 @@ func CreateFilesModel_manual(Table1 *types.Table, DirTemplatesModel, DirReadyMod return err } + +// CreateFilesUpdateEveryColumn - создаёт 1 файл в папке model, для каждой колонки функция Update() +func CreateFilesUpdateEveryColumn(Table1 *types.Table) error { + var err error + + TableName := strings.ToLower(Table1.Name) + //ModelName := Table1.NameGo + + //чтение файлов + DirBin := micro.ProgramDir_bin() + DirTemplates := DirBin + config.Settings.TEMPLATE_FOLDERNAME + micro.SeparatorFile() + DirReady := DirBin + config.Settings.READY_FOLDERNAME + micro.SeparatorFile() + DirTemplatesModel := DirTemplates + config.Settings.TEMPLATE_FOLDERNAME_MODEL + micro.SeparatorFile() + DirReadyModel := DirReady + config.Settings.TEMPLATE_FOLDERNAME_MODEL + micro.SeparatorFile() + TableName + micro.SeparatorFile() + + //создадим папку готовых файлов + folders.CreateFolder(DirReadyModel) + + FilenameTemplateModel := DirTemplatesModel + constants.MODEL_TABLE_UPDATE_FILENAME + FilenameReadyModel := DirReadyModel + config.Settings.PREFIX_MODEL + TableName + "_update.go" + + //создадим папку готовых файлов + folders.CreateFolder(DirReadyModel) + + //чтение файла шаблона + bytes, err := os.ReadFile(FilenameTemplateModel) + if err != nil { + log.Panic("ReadFile() ", FilenameTemplateModel, " error: ", err) + } + TextModel := string(bytes) + + //заменим имя пакета на новое + TextModel = create_files.ReplacePackageName(TextModel, DirReadyModel) + + //замена импортов на новые URL + if config.Settings.USE_DEFAULT_TEMPLATE == true { + TextModel = create_files.DeleteTemplateRepositoryImports(TextModel) + + ConstantsURL := create_files.FindDBConstantsURL() + TextModel = create_files.AddImport(TextModel, ConstantsURL) + } + + TextModel = create_files.CheckAndAddImportTime_FromText(TextModel) + + //удаление пустого импорта + TextModel = create_files.DeleteEmptyImport(TextModel) + + //сортировка по названию таблиц + keys := make([]string, 0, len(Table1.MapColumns)) + for k := range Table1.MapColumns { + keys = append(keys, k) + } + sort.Strings(keys) + + //найдём новый текст для каждой таблицы + TextNew := "" + for _, key1 := range keys { + Column1, ok := Table1.MapColumns[key1] + if ok == false { + log.Panic("CreateFilesUpdateEveryColumn() Table1.MapColumns[key1] = false") + } + if create_files.Is_Common_Сolumn(Column1) == true { + continue + } + TextNew1 := FindTextUpdateEveryColumn(Table1, Column1) + TextNew = TextNew + TextNew1 + } + + TextModel = TextModel + TextNew + + //запись файла + err = os.WriteFile(FilenameReadyModel, []byte(TextModel), constants.FILE_PERMISSIONS) + + return err +} + +func FindTextUpdateEveryColumn(Table1 *types.Table, Column1 *types.Column) string { + Otvet := "" + + ModelName := Table1.NameGo + ColumnName := Column1.NameGo + + Otvet = ` +// Update_` + ColumnName + ` - изменяет объект в БД по ID, присваивает ` + ColumnName + ` +func (m *` + ModelName + `) Update_` + ColumnName + `() error { + if Crud_` + ModelName + ` == nil { + return constants.ErrorCrudIsNotInit + } + + err := Crud_` + ModelName + `.Update_` + ColumnName + `(m) + + return err +} +` + + return Otvet +} + +func AddInterfaceUpdateEveryColumn(TextModel string, Table1 *types.Table) string { + Otvet := TextModel + + //сортировка по названию таблиц + keys := make([]string, 0, len(Table1.MapColumns)) + for k := range Table1.MapColumns { + keys = append(keys, k) + } + sort.Strings(keys) + + //найдём новый текст для каждой таблицы + //TextNew := "" + for _, key1 := range keys { + Column1, ok := Table1.MapColumns[key1] + if ok == false { + log.Panic("CreateFilesUpdateEveryColumn() Table1.MapColumns[key1] = false") + } + if create_files.Is_Common_Сolumn(Column1) == true { + continue + } + TextNew1 := FindTextInterfaceUpdateEveryColumn(Table1, Column1) + Otvet = create_files.AddInterfaceFunction(Otvet, TextNew1) + //pos1 := strings.Index(TextModel, TextNew1) + //if pos1 >= 0 { //только если нет такой функции в интерфейсе + // TextNew = TextNew + TextNew1 + //} + } + + return Otvet +} + +func FindTextInterfaceUpdateEveryColumn(Table1 *types.Table, Column1 *types.Column) string { + Otvet := "" + + ModelName := Table1.NameGo + ColumnName := Column1.NameGo + + Otvet = ` + Update_` + ColumnName + `(*` + ModelName + `) error` + + return Otvet +} diff --git a/internal/create_files/protobuf/protobuf.go b/internal/create_files/protobuf/protobuf.go index 2dcb3d4..7889c1e 100644 --- a/internal/create_files/protobuf/protobuf.go +++ b/internal/create_files/protobuf/protobuf.go @@ -83,6 +83,7 @@ func CreateFileProto(MapAll map[string]*types.Table) error { } TextProtoNew = TextProtoNew + FindTextProtoTable1(TextProto, Table1) + TextProtoNew = TextProtoNew + FindTextProtoTable1_UpdateEveryColumn(TextProto, Table1) } //найдём куда вставить текст @@ -308,3 +309,100 @@ func TextFindByExtId(ModelName string) string { return Otvet } + +// FindTextProtoTable1_UpdateEveryColumn - возвращает текст всех функций .proto для таблицы, обновления каждого поля таблицы +func FindTextProtoTable1_UpdateEveryColumn(TextProto string, Table1 *types.Table) string { + Otvet := "\n" //"\n\t//\n" + + //ModelName := Table1.NameGo + + //сортировка по названию таблиц + keys := make([]string, 0, len(Table1.MapColumns)) + for k := range Table1.MapColumns { + keys = append(keys, k) + } + sort.Strings(keys) + + //найдём новый текст для каждой таблицы + for _, key1 := range keys { + Column1, ok := Table1.MapColumns[key1] + if ok == false { + log.Panic("FindTextProtoTable1_UpdateEveryColumn() Table1.MapColumns[key1] = false") + } + if create_files.Is_Common_Сolumn(Column1) == true { + continue + } + + Otvet1 := FindTextUpdateEveryColumn(TextProto, Table1, Column1) + //TextFind := "rpc " + Table1.NameGo + "_" + //pos1 := FindLastGoodPos(TextProto, TextFind) + //if pos1 > 0 { + // Otvet = Otvet[:pos1] + Otvet1 + Otvet[pos1:] + //} else { + // Otvet = Otvet + Otvet1 + //} + Otvet = Otvet + Otvet1 + } + + return Otvet +} + +// FindTextUpdateEveryColumn - возвращает текст .proto функции Update_ColumnName() +func FindTextUpdateEveryColumn(TextProto string, Table1 *types.Table, Column1 *types.Column) string { + Otvet := "" + Otvet2 := TextUpdateEveryColumn(Table1, Column1) + + //проверка такой текст уже есть + pos1 := strings.Index(TextProto, Otvet2) + if pos1 >= 0 { + return Otvet + } + + Otvet = "\t" + Otvet2 + "\n" + + return Otvet +} + +// FindTextRequest - возвращает имя message из .proto, в зависимости от типа +func FindTextRequest(TypeGo string) string { + Otvet := "RequestID" + + switch TypeGo { + case "int", "int64": + + Otvet = "RequestId" + case "int32": + Otvet = "RequestInt32" + case "string": + + Otvet = "RequestString" + case "time.Time": + + Otvet = "RequestDate" + case "float32": + Otvet = "RequestFloat32" + case "float64": + Otvet = "RequestFloat64" + case "bool": + Otvet = "RequestBool" + } + + return Otvet +} + +// TextUpdateEveryColumn - возвращает текст .proto функции Update_ColumnName() +func TextUpdateEveryColumn(Table1 *types.Table, Column1 *types.Column) string { + Otvet := "" + + ModelName := Table1.NameGo + + TextRequest := "RequestID" + TypeGo := Column1.TypeGo + TextRequest = FindTextRequest(TypeGo) + ColumnName := Column1.NameGo + + Otvet = "rpc " + ModelName + "_Update_" + ColumnName + "(" + TextRequest + ") returns (ResponseEmpty) {}" + //Otvet = Otvet + "\n" + + return Otvet +} diff --git a/internal/create_files/protobuf/protobuf_test.go b/internal/create_files/protobuf/protobuf_test.go index aff9af7..d2eb9c3 100644 --- a/internal/create_files/protobuf/protobuf_test.go +++ b/internal/create_files/protobuf/protobuf_test.go @@ -1 +1,15 @@ package protobuf + +import "testing" + +func TestFindLastGoodPos(t *testing.T) { + s := "123456\n789" + pos1 := FindLastGoodPos(s, "5") + if pos1 < 0 { + t.Error("FindLastGoodPos() error: ", pos1) + } + s2 := s[pos1:] + if s2 != "789" { + t.Error("FindLastGoodPos() error: ", s2) + } +}