diff --git a/components/contracts/category.go b/components/contracts/category.go index fc71419..b9930ec 100644 --- a/components/contracts/category.go +++ b/components/contracts/category.go @@ -52,6 +52,14 @@ type ( // UpdateDescriptionAtomic updates 'Description' into persistent data store through a transaction and // refreshes the in-memory cache after successful commit. UpdateDescriptionAtomic(transaction ITransaction, description string, editor Identity) + // SortOrder returns 'SortOrder' of this 'Category' instance. + SortOrder() float32 + // UpdateSortOrder directly updates 'SortOrder' into persistent data store and + // refreshes the in-memory cache after successful update. + UpdateSortOrder(sortOrder float32, editor Identity) + // UpdateSortOrderAtomic updates 'SortOrder' into persistent data store through a transaction and + // refreshes the in-memory cache after successful commit. + UpdateSortOrderAtomic(transaction ITransaction, sortOrder float32, editor Identity) } ICategoryCollection interface { diff --git a/components/contracts/model/category.go b/components/contracts/model/category.go index 66823aa..238c1b3 100644 --- a/components/contracts/model/category.go +++ b/components/contracts/model/category.go @@ -32,5 +32,7 @@ type ( UpdateTitleAtomic(transaction IRepositoryTransaction, id int64, value string, editor int64) error UpdateDescription(id int64, value string, editor int64) error UpdateDescriptionAtomic(transaction IRepositoryTransaction, id int64, value string, editor int64) error + UpdateSortOrder(id int64, value float32, editor int64) error + UpdateSortOrderAtomic(transaction IRepositoryTransaction, id int64, value float32, editor int64) error } ) diff --git a/components/core/category.go b/components/core/category.go index 19162e5..3667419 100644 --- a/components/core/category.go +++ b/components/core/category.go @@ -39,7 +39,8 @@ func NewCategory(id int64, categoryTypeId int64, categoryId int64, title string, func NewCategoryFromEntity(entity ICategoryEntity) (ICategory, error) { instance := &category{ object: object{ - id: entity.Id(), + id: entity.Id(), + sortOrder: entity.SortOrder(), }, categoryTypeId: entity.CategoryTypeId(), categoryId: entity.CategoryId(), @@ -155,6 +156,28 @@ func (category *category) UpdateDescriptionAtomic(transaction ITransaction, desc } } +func (category *category) SortOrder() float32 { + return category.sortOrder +} + +func (category *category) UpdateSortOrder(sortOrder float32, editor Identity) { + if err := repository.Categories.UpdateSortOrder(category.id, sortOrder, editor.Id()); err != nil { + panic(err.Error()) + } + + category.sortOrder = sortOrder +} + +func (category *category) UpdateSortOrderAtomic(transaction ITransaction, sortOrder float32, editor Identity) { + transaction.OnCommit(func() { + category.sortOrder = sortOrder + }) + + if err := repository.Categories.UpdateSortOrderAtomic(transaction, category.id, sortOrder, editor.Id()); err != nil { + panic(err.Error()) + } +} + func (category *category) Validate() error { return nil } diff --git a/components/core/category_manager.go b/components/core/category_manager.go index ba65c2f..80dd7d5 100644 --- a/components/core/category_manager.go +++ b/components/core/category_manager.go @@ -129,32 +129,32 @@ func (manager *categoryManager) GetCategory(id int64, _ Identity) (ICategory, er } func (manager *categoryManager) AddCategory(categoryTypeId int64, categoryId int64, title string, description string, editor Identity) (ICategory, error) { - categoryEntity := NewCategoryEntity(manager.UniqueId(), categoryTypeId, categoryId, title, description) + categoryEntity := NewCategoryEntity(manager.UniqueId(), categoryTypeId, categoryId, title, description, 0) return manager.Apply(categoryEntity, repository.Categories.Add, manager.cache.Put, editor) } func (manager *categoryManager) AddCategoryWithCustomId(id int64, categoryTypeId int64, categoryId int64, title string, description string, editor Identity) (ICategory, error) { - categoryEntity := NewCategoryEntity(id, categoryTypeId, categoryId, title, description) + categoryEntity := NewCategoryEntity(id, categoryTypeId, categoryId, title, description, 0) return manager.Apply(categoryEntity, repository.Categories.Add, manager.cache.Put, editor) } func (manager *categoryManager) AddCategoryObject(category ICategory, editor Identity) (ICategory, error) { - categoryEntity := NewCategoryEntity(manager.UniqueId(), category.CategoryTypeId(), category.CategoryId(), category.Title(), category.Description()) + categoryEntity := NewCategoryEntity(manager.UniqueId(), category.CategoryTypeId(), category.CategoryId(), category.Title(), category.Description(), 0) return manager.Apply(categoryEntity, repository.Categories.Add, manager.cache.Put, editor) } func (manager *categoryManager) AddCategoryAtomic(transaction ITransaction, categoryTypeId int64, categoryId int64, title string, description string, editor Identity) (ICategory, error) { - categoryEntity := NewCategoryEntity(manager.UniqueId(), categoryTypeId, categoryId, title, description) + categoryEntity := NewCategoryEntity(manager.UniqueId(), categoryTypeId, categoryId, title, description, 0) return manager.ApplyAtomic(transaction, categoryEntity, repository.Categories.AddAtomic, manager.cache.Put, editor) } func (manager *categoryManager) AddCategoryWithCustomIdAtomic(id int64, transaction ITransaction, categoryTypeId int64, categoryId int64, title string, description string, editor Identity) (ICategory, error) { - categoryEntity := NewCategoryEntity(id, categoryTypeId, categoryId, title, description) + categoryEntity := NewCategoryEntity(id, categoryTypeId, categoryId, title, description, 0) return manager.ApplyAtomic(transaction, categoryEntity, repository.Categories.AddAtomic, manager.cache.Put, editor) } func (manager *categoryManager) AddCategoryObjectAtomic(transaction ITransaction, category ICategory, editor Identity) (ICategory, error) { - categoryEntity := NewCategoryEntity(manager.UniqueId(), category.CategoryTypeId(), category.CategoryId(), category.Title(), category.Description()) + categoryEntity := NewCategoryEntity(manager.UniqueId(), category.CategoryTypeId(), category.CategoryId(), category.Title(), category.Description(), 0) return manager.ApplyAtomic(transaction, categoryEntity, repository.Categories.AddAtomic, manager.cache.Put, editor) } @@ -171,22 +171,22 @@ func (manager *categoryManager) Log(categoryTypeId int64, categoryId int64, titl } func (manager *categoryManager) UpdateCategory(id int64, categoryTypeId int64, categoryId int64, title string, description string, editor Identity) (ICategory, error) { - categoryEntity := NewCategoryEntity(id, categoryTypeId, categoryId, title, description) + categoryEntity := NewCategoryEntity(id, categoryTypeId, categoryId, title, description, 0) return manager.Apply(categoryEntity, repository.Categories.Update, manager.cache.Put, editor) } func (manager *categoryManager) UpdateCategoryObject(id int64, category ICategory, editor Identity) (ICategory, error) { - categoryEntity := NewCategoryEntity(id, category.Id(), category.Id(), category.Title(), category.Description()) + categoryEntity := NewCategoryEntity(id, category.Id(), category.Id(), category.Title(), category.Description(), 0) return manager.Apply(categoryEntity, repository.Categories.Update, manager.cache.Put, editor) } func (manager *categoryManager) UpdateCategoryAtomic(transaction ITransaction, id int64, categoryTypeId int64, categoryId int64, title string, description string, editor Identity) (ICategory, error) { - categoryEntity := NewCategoryEntity(id, categoryTypeId, categoryId, title, description) + categoryEntity := NewCategoryEntity(id, categoryTypeId, categoryId, title, description, 0) return manager.ApplyAtomic(transaction, categoryEntity, repository.Categories.UpdateAtomic, manager.cache.Put, editor) } func (manager *categoryManager) UpdateCategoryObjectAtomic(transaction ITransaction, id int64, category ICategory, editor Identity) (ICategory, error) { - categoryEntity := NewCategoryEntity(id, category.Id(), category.Id(), category.Title(), category.Description()) + categoryEntity := NewCategoryEntity(id, category.Id(), category.Id(), category.Title(), category.Description(), 0) return manager.ApplyAtomic(transaction, categoryEntity, repository.Categories.UpdateAtomic, manager.cache.Put, editor) } @@ -207,12 +207,12 @@ func (manager *categoryManager) AddOrUpdateCategoryObjectAtomic(transaction ITra } func (manager *categoryManager) RemoveCategory(id int64, editor Identity) (ICategory, error) { - categoryEntity := NewCategoryEntity(id, 0, 0, "", "") + categoryEntity := NewCategoryEntity(id, 0, 0, "", "", 0) return manager.Apply(categoryEntity, repository.Categories.Remove, manager.cache.Remove, editor) } func (manager *categoryManager) RemoveCategoryAtomic(transaction ITransaction, id int64, editor Identity) (ICategory, error) { - categoryEntity := NewCategoryEntity(id, 0, 0, "", "") + categoryEntity := NewCategoryEntity(id, 0, 0, "", "", 0) return manager.ApplyAtomic(transaction, categoryEntity, repository.Categories.RemoveAtomic, manager.cache.Remove, editor) } diff --git a/components/model/entity/category_entity.go b/components/model/entity/category_entity.go index 5be9c0b..4033e9d 100644 --- a/components/model/entity/category_entity.go +++ b/components/model/entity/category_entity.go @@ -19,9 +19,9 @@ type categoryEntity struct { DescriptionField string `json:"description" storage:"VARCHAR(64)" default:"''"` } -func NewCategoryEntity(id int64, categoryTypeId int64, categoryId int64, title string, description string) ICategoryEntity { +func NewCategoryEntity(id int64, categoryTypeId int64, categoryId int64, title string, description string, sortOrder float32) ICategoryEntity { return &categoryEntity{ - entity: entity{IdField: id}, + entity: entity{IdField: id, SortOrderField: sortOrder}, CategoryTypeIdField: categoryTypeId, CategoryIdField: categoryId, TitleField: title, diff --git a/components/model/repository/categories_repository.go b/components/model/repository/categories_repository.go index 056718f..8784330 100644 --- a/components/model/repository/categories_repository.go +++ b/components/model/repository/categories_repository.go @@ -44,7 +44,7 @@ func (repository *categoriesRepository) FetchById(id int64) (ICategoryEntity, er } // language=SQL - query := `SELECT "id", "category_type_id", "category_id", "title", "description" FROM "categories" WHERE "id" = $1 AND "status" = 0;` + query := `SELECT "id", "category_type_id", "category_id", "title", "description", "sort_order" FROM "categories" WHERE "id" = $1 AND "status" = 0;` var categoryEntity ICategoryEntity if err := repository.database.QuerySingle(func(cursor ICursor) error { @@ -54,13 +54,14 @@ func (repository *categoriesRepository) FetchById(id int64) (ICategoryEntity, er categoryId int64 title string description string + sortOrder float32 ) - if err := cursor.Scan(&id, &categoryTypeId, &categoryId, &title, &description); err != nil { + if err := cursor.Scan(&id, &categoryTypeId, &categoryId, &title, &description, &sortOrder); err != nil { return err } - categoryEntity = NewCategoryEntity(id, categoryTypeId, categoryId, title, description) + categoryEntity = NewCategoryEntity(id, categoryTypeId, categoryId, title, description, sortOrder) return nil }, query, id); err != nil { return nil, err @@ -111,7 +112,7 @@ func (repository *categoriesRepository) RemoveAtomic(transaction IRepositoryTran func (repository *categoriesRepository) FetchAll() (CategoryEntities, error) { // language=SQL - query := `SELECT "id", "category_type_id", "category_id", "title", "description" FROM "categories" WHERE "id" > 0 AND "status" = 0;` + query := `SELECT "id", "category_type_id", "category_id", "title", "description", "sort_order" FROM "categories" WHERE "id" > 0 AND "status" = 0;` var categoryEntities CategoryEntities if err := repository.database.Query(func(cursor ICursor) error { @@ -121,13 +122,14 @@ func (repository *categoriesRepository) FetchAll() (CategoryEntities, error) { categoryId int64 title string description string + sortOrder float32 ) - if err := cursor.Scan(&id, &categoryTypeId, &categoryId, &title, &description); err != nil { + if err := cursor.Scan(&id, &categoryTypeId, &categoryId, &title, &description, &sortOrder); err != nil { return err } - categoryEntities = append(categoryEntities, NewCategoryEntity(id, categoryTypeId, categoryId, title, description)) + categoryEntities = append(categoryEntities, NewCategoryEntity(id, categoryTypeId, categoryId, title, description, sortOrder)) return nil }, query); err != nil { return nil, err @@ -154,7 +156,7 @@ func (repository *categoriesRepository) FetchAllByCategory(categoryId int64) (Ca func (repository *categoriesRepository) FetchAllByDependency(dependencyName string, dependencyId int64) (CategoryEntities, error) { // language=SQL - query := `SELECT "id", "category_type_id", "category_id", "title", "description" FROM "categories" WHERE "id" > 0 AND "status" = 0` + query := `SELECT "id", "category_type_id", "category_id", "title", "description", "sort_order" FROM "categories" WHERE "id" > 0 AND "status" = 0` query += ` AND "` + dependencyName + `" = $1;` var categoryEntities CategoryEntities @@ -165,13 +167,14 @@ func (repository *categoriesRepository) FetchAllByDependency(dependencyName stri categoryId int64 title string description string + sortOrder float32 ) - if err := cursor.Scan(&id, &categoryTypeId, &categoryId, &title, &description); err != nil { + if err := cursor.Scan(&id, &categoryTypeId, &categoryId, &title, &description, &sortOrder); err != nil { return err } - categoryEntities = append(categoryEntities, NewCategoryEntity(id, categoryTypeId, categoryId, title, description)) + categoryEntities = append(categoryEntities, NewCategoryEntity(id, categoryTypeId, categoryId, title, description, sortOrder)) return nil }, query, dependencyId); err != nil { return nil, err @@ -219,3 +222,23 @@ func (repository *categoriesRepository) UpdateDescriptionAtomic(transaction IRep query := `UPDATE "categories" SET "description" = $1, "editor" = $2 WHERE "id" = $3;` return repository.database.UpdateSingleAtomic(transaction, query, value, editor, id) } + +func (repository *categoriesRepository) UpdateSortOrder(id int64, value float32, editor int64) error { + if id <= 0 { + return ERROR_INVALID_PARAMETERS + } + + // language=SQL + query := `UPDATE "categories" SET "sort_order" = $1, "editor" = $2 WHERE "id" = $3;` + return repository.database.UpdateSingle(query, value, editor, id) +} + +func (repository *categoriesRepository) UpdateSortOrderAtomic(transaction IRepositoryTransaction, id int64, value float32, editor int64) error { + if id <= 0 { + return ERROR_INVALID_PARAMETERS + } + + // language=SQL + query := `UPDATE "categories" SET "sort_order" = $1, "editor" = $2 WHERE "id" = $3;` + return repository.database.UpdateSingleAtomic(transaction, query, value, editor, id) +} diff --git a/components/model/repository/categories_repository_test.go b/components/model/repository/categories_repository_test.go index 89dc75a..2c96c2b 100644 --- a/components/model/repository/categories_repository_test.go +++ b/components/model/repository/categories_repository_test.go @@ -14,6 +14,7 @@ func TestCategoriesRepository_Add(test *testing.T) { categoryId int64 title string description string + sortOrder float32 } testCases := []struct { @@ -30,6 +31,7 @@ func TestCategoriesRepository_Add(test *testing.T) { categoryId: 0, title: "title", description: "description", + sortOrder: 0, }, }, { @@ -41,6 +43,7 @@ func TestCategoriesRepository_Add(test *testing.T) { categoryId: 0, title: "title", description: "description", + sortOrder: 0, }, }, { @@ -52,13 +55,14 @@ func TestCategoriesRepository_Add(test *testing.T) { categoryId: 0, title: "title", description: "description", + sortOrder: 0, }, }, } for _, testCase := range testCases { test.Run(testCase.name, func(test *testing.T) { - entity := NewCategoryEntity(testCase.arguments.id, testCase.arguments.categoryTypeId, testCase.arguments.categoryId, testCase.arguments.title, testCase.arguments.description) + entity := NewCategoryEntity(testCase.arguments.id, testCase.arguments.categoryTypeId, testCase.arguments.categoryId, testCase.arguments.title, testCase.arguments.description, testCase.arguments.sortOrder) if result := Categories.Add(entity, -1) == nil; result != testCase.expectation { test.Errorf("Categories.Add() = %v, expected %v", result, testCase.expectation) } @@ -118,6 +122,7 @@ func TestCategoriesRepository_Update(test *testing.T) { categoryId int64 title string description string + sortOrder float32 } testCases := []struct { @@ -134,6 +139,7 @@ func TestCategoriesRepository_Update(test *testing.T) { categoryId: 0, title: "title", description: "description", + sortOrder: 0, }, }, { @@ -145,6 +151,7 @@ func TestCategoriesRepository_Update(test *testing.T) { categoryId: 0, title: "title", description: "description", + sortOrder: 0, }, }, { @@ -156,13 +163,14 @@ func TestCategoriesRepository_Update(test *testing.T) { categoryId: 0, title: "title", description: "description", + sortOrder: 0, }, }, } for _, testCase := range testCases { test.Run(testCase.name, func(test *testing.T) { - entity := NewCategoryEntity(testCase.arguments.id, testCase.arguments.categoryTypeId, testCase.arguments.categoryId, testCase.arguments.title, testCase.arguments.description) + entity := NewCategoryEntity(testCase.arguments.id, testCase.arguments.categoryTypeId, testCase.arguments.categoryId, testCase.arguments.title, testCase.arguments.description, testCase.arguments.sortOrder) if result := Categories.Update(entity, -1) == nil; result != testCase.expectation { test.Errorf("Categories.Update() = %v, expected %v", result, testCase.expectation) } @@ -177,6 +185,7 @@ func TestCategoriesRepository_Remove(test *testing.T) { categoryId int64 title string description string + sortOrder float32 } testCases := []struct { @@ -209,7 +218,7 @@ func TestCategoriesRepository_Remove(test *testing.T) { for _, testCase := range testCases { test.Run(testCase.name, func(test *testing.T) { - entity := NewCategoryEntity(testCase.arguments.id, testCase.arguments.categoryTypeId, testCase.arguments.categoryId, testCase.arguments.title, testCase.arguments.description) + entity := NewCategoryEntity(testCase.arguments.id, testCase.arguments.categoryTypeId, testCase.arguments.categoryId, testCase.arguments.title, testCase.arguments.description, testCase.arguments.sortOrder) if result := Categories.Remove(entity, -1) == nil; result != testCase.expectation { test.Errorf("Categories.Remove() = %v, expected %v", result, testCase.expectation) }