From 299fcf949ba8b25c3d886229ba7d994c151e4a66 Mon Sep 17 00:00:00 2001 From: ericprd Date: Wed, 5 Mar 2025 23:13:24 +0800 Subject: [PATCH] feat: update and delete tags and categories --- .gitignore | 1 + database/category_model.go | 4 +- database/tag_module.go | 4 +- internal/accessor/category/delete.go | 14 ++++ internal/accessor/category/impl.go | 6 +- internal/accessor/category/update.go | 2 +- internal/accessor/tag/create_model.go | 22 ----- internal/accessor/tag/delete.go | 14 ++++ .../tag/{get_bulk.go => get_by_ids.go} | 0 internal/accessor/tag/impl.go | 3 +- internal/accessor/tag/update.go | 23 ++++++ internal/api/http/category/delete.go | 53 ++++++++++++ internal/api/http/category/module.go | 1 + internal/api/http/tag/delete.go | 53 ++++++++++++ internal/api/http/tag/module.go | 2 + internal/api/http/tag/update.go | 82 +++++++++++++++++++ internal/services/category/delete.go | 5 ++ internal/services/category/impl.go | 1 + internal/services/tag/create.go | 2 +- internal/services/tag/delete.go | 5 ++ internal/services/tag/impl.go | 2 + internal/services/tag/update.go | 16 ++++ 22 files changed, 283 insertions(+), 32 deletions(-) create mode 100644 internal/accessor/category/delete.go delete mode 100644 internal/accessor/tag/create_model.go create mode 100644 internal/accessor/tag/delete.go rename internal/accessor/tag/{get_bulk.go => get_by_ids.go} (100%) create mode 100644 internal/accessor/tag/update.go create mode 100644 internal/api/http/category/delete.go create mode 100644 internal/api/http/tag/delete.go create mode 100644 internal/api/http/tag/update.go create mode 100644 internal/services/category/delete.go create mode 100644 internal/services/tag/delete.go create mode 100644 internal/services/tag/update.go diff --git a/.gitignore b/.gitignore index d84cea3..0b433b3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ bin .env +.DS_STORE diff --git a/database/category_model.go b/database/category_model.go index 457ac50..474022c 100644 --- a/database/category_model.go +++ b/database/category_model.go @@ -6,8 +6,8 @@ import ( type Category struct { ID string `gorm:"primaryKey" json:"id"` - Name string `gorm:"not null;unique" json:"name"` - Code string `gorm:"not null" json:"code"` + Name string `gorm:"not null" json:"name"` + Code string `gorm:"not null;unique" json:"code"` CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"` UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"` DeletedAt time.Time `gorm:"default:null" json:"deleted_at"` diff --git a/database/tag_module.go b/database/tag_module.go index 0d00366..da6a06c 100644 --- a/database/tag_module.go +++ b/database/tag_module.go @@ -6,8 +6,8 @@ import ( type Tag struct { ID string `gorm:"primaryKey" json:"id"` - Name string `gorm:"not null;unique" json:"name"` - Code string `gorm:"not null" json:"code"` + Name string `gorm:"not null" json:"name"` + Code string `gorm:"not null;unique" json:"code"` CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"` UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"` DeletedAt time.Time `gorm:"default:null" json:"deleted_at"` diff --git a/internal/accessor/category/delete.go b/internal/accessor/category/delete.go new file mode 100644 index 0000000..3427c77 --- /dev/null +++ b/internal/accessor/category/delete.go @@ -0,0 +1,14 @@ +package categoryrepository + +import ( + "fmt" + categorydomain "legalgo-BE-go/internal/domain/category" +) + +func (a *accessor) Delete(id string) error { + if err := a.DB.Delete(&categorydomain.Category{}, "id = ?", id).Error; err != nil { + return fmt.Errorf("failed to delete category %s : %v", id, err) + } + + return nil +} diff --git a/internal/accessor/category/impl.go b/internal/accessor/category/impl.go index d9e3899..bbf0f2b 100644 --- a/internal/accessor/category/impl.go +++ b/internal/accessor/category/impl.go @@ -10,11 +10,11 @@ type accessor struct { } type Category interface { - CreateModel(categorydomain.CategoryReq) error - Update(categorydomain.Category) error - GetAllModel() ([]categorydomain.Category, error) GetByIDs([]string) ([]categorydomain.Category, error) + CreateModel(categorydomain.CategoryReq) error + Update(categorydomain.Category) error + Delete(string) error } func New( diff --git a/internal/accessor/category/update.go b/internal/accessor/category/update.go index 8f23d26..bd07ce3 100644 --- a/internal/accessor/category/update.go +++ b/internal/accessor/category/update.go @@ -11,7 +11,7 @@ func (a *accessor) Update(spec categorydomain.Category) error { if err := a.DB.Clauses(clause.OnConflict{ Columns: []clause.Column{{Name: "id"}}, DoUpdates: clause.AssignmentColumns([]string{"name", "code", "updated_at"}), - }).Save(&spec).Error; err != nil { + }).Select("name", "code", "updated_at").Save(&spec).Error; err != nil { return fmt.Errorf("failed to update category: %v", err) } diff --git a/internal/accessor/tag/create_model.go b/internal/accessor/tag/create_model.go deleted file mode 100644 index 77988c3..0000000 --- a/internal/accessor/tag/create_model.go +++ /dev/null @@ -1,22 +0,0 @@ -package tagrepository - -import ( - "legalgo-BE-go/database" - tagdomain "legalgo-BE-go/internal/domain/tag" - - "github.com/google/uuid" -) - -func (acc *accessor) CreateModel(spec tagdomain.TagReq) error { - data := &database.Tag{ - ID: uuid.NewString(), - Code: spec.Code, - Name: spec.Name, - } - - if err := acc.DB.Create(&data).Error; err != nil { - return err - } - - return nil -} diff --git a/internal/accessor/tag/delete.go b/internal/accessor/tag/delete.go new file mode 100644 index 0000000..38ed002 --- /dev/null +++ b/internal/accessor/tag/delete.go @@ -0,0 +1,14 @@ +package tagrepository + +import ( + "fmt" + tagdomain "legalgo-BE-go/internal/domain/tag" +) + +func (a *accessor) Delete(id string) error { + if err := a.DB.Delete(&tagdomain.Tag{}, "id = ?", id).Error; err != nil { + return fmt.Errorf("failed to delete category %s : %v", id, err) + } + + return nil +} diff --git a/internal/accessor/tag/get_bulk.go b/internal/accessor/tag/get_by_ids.go similarity index 100% rename from internal/accessor/tag/get_bulk.go rename to internal/accessor/tag/get_by_ids.go diff --git a/internal/accessor/tag/impl.go b/internal/accessor/tag/impl.go index 7fbd5dd..bdc5b4d 100644 --- a/internal/accessor/tag/impl.go +++ b/internal/accessor/tag/impl.go @@ -11,9 +11,10 @@ type accessor struct { type TagAccessor interface { Create(tagdomain.TagReq) error - CreateModel(tagdomain.TagReq) error GetAll() ([]tagdomain.Tag, error) GetByIDs([]string) ([]tagdomain.Tag, error) + Update(tagdomain.Tag) error + Delete(string) error } func New( diff --git a/internal/accessor/tag/update.go b/internal/accessor/tag/update.go new file mode 100644 index 0000000..9200320 --- /dev/null +++ b/internal/accessor/tag/update.go @@ -0,0 +1,23 @@ +package tagrepository + +import ( + "fmt" + tagdomain "legalgo-BE-go/internal/domain/tag" + + "gorm.io/gorm/clause" +) + +func (a *accessor) Update(spec tagdomain.Tag) error { + if err := a.DB.Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "id"}}, + DoUpdates: clause.AssignmentColumns([]string{ + "name", + "code", + "updated_at", + }), + }).Select("name", "code", "updated_at").Save(&spec).Error; err != nil { + return fmt.Errorf("failed to update tag: %v", err) + } + + return nil +} diff --git a/internal/api/http/category/delete.go b/internal/api/http/category/delete.go new file mode 100644 index 0000000..5b50869 --- /dev/null +++ b/internal/api/http/category/delete.go @@ -0,0 +1,53 @@ +package categoryhttp + +import ( + "fmt" + authmiddleware "legalgo-BE-go/internal/api/http/middleware/auth" + categorysvc "legalgo-BE-go/internal/services/category" + "legalgo-BE-go/internal/utilities/response" + "net/http" + + "github.com/go-chi/chi/v5" +) + +func Delete( + router chi.Router, + categorySvc categorysvc.Category, +) { + router. + With(authmiddleware.Authorize()). + Delete("/category/{category_id}/delete", func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + categoryID := chi.URLParam(r, "category_id") + + if categoryID == "" { + response.RespondJsonErrorWithCode( + ctx, + w, + fmt.Errorf("category id is not provided"), + response.ErrBadRequest.Code, + response.ErrBadRequest.HttpCode, + "category id is not provided", + ) + return + } + + if err := categorySvc.Delete(categoryID); err != nil { + response.RespondJsonErrorWithCode( + ctx, + w, + err, + response.ErrBadRequest.Code, + response.ErrBadRequest.HttpCode, + err.Error(), + ) + return + } + + response.RespondJsonSuccess(ctx, w, struct { + Message string + }{ + Message: "category has been deleted", + }) + }) +} diff --git a/internal/api/http/category/module.go b/internal/api/http/category/module.go index 8e1a902..040b999 100644 --- a/internal/api/http/category/module.go +++ b/internal/api/http/category/module.go @@ -6,4 +6,5 @@ var Module = fx.Module("categories", fx.Invoke( Create, GetAll, Update, + Delete, )) diff --git a/internal/api/http/tag/delete.go b/internal/api/http/tag/delete.go new file mode 100644 index 0000000..748ae9a --- /dev/null +++ b/internal/api/http/tag/delete.go @@ -0,0 +1,53 @@ +package taghttp + +import ( + "fmt" + authmiddleware "legalgo-BE-go/internal/api/http/middleware/auth" + tagsvc "legalgo-BE-go/internal/services/tag" + "legalgo-BE-go/internal/utilities/response" + "net/http" + + "github.com/go-chi/chi/v5" +) + +func Delete( + router chi.Router, + tagSvc tagsvc.Tag, +) { + router. + With(authmiddleware.Authorize()). + Delete("/tag/{category_id}/delete", func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + categoryID := chi.URLParam(r, "category_id") + + if categoryID == "" { + response.RespondJsonErrorWithCode( + ctx, + w, + fmt.Errorf("category id is not provided"), + response.ErrBadRequest.Code, + response.ErrBadRequest.HttpCode, + "category id is not provided", + ) + return + } + + if err := tagSvc.Delete(categoryID); err != nil { + response.RespondJsonErrorWithCode( + ctx, + w, + err, + response.ErrBadRequest.Code, + response.ErrBadRequest.HttpCode, + err.Error(), + ) + return + } + + response.RespondJsonSuccess(ctx, w, struct { + Message string + }{ + Message: "tag has been deleted", + }) + }) +} diff --git a/internal/api/http/tag/module.go b/internal/api/http/tag/module.go index b62951c..a9110fb 100644 --- a/internal/api/http/tag/module.go +++ b/internal/api/http/tag/module.go @@ -5,4 +5,6 @@ import "go.uber.org/fx" var Module = fx.Module("tag", fx.Invoke( Create, GetAll, + Update, + Delete, )) diff --git a/internal/api/http/tag/update.go b/internal/api/http/tag/update.go new file mode 100644 index 0000000..3d9a11b --- /dev/null +++ b/internal/api/http/tag/update.go @@ -0,0 +1,82 @@ +package taghttp + +import ( + "fmt" + authmiddleware "legalgo-BE-go/internal/api/http/middleware/auth" + tagdomain "legalgo-BE-go/internal/domain/tag" + tagsvc "legalgo-BE-go/internal/services/tag" + "legalgo-BE-go/internal/utilities/response" + "legalgo-BE-go/internal/utilities/utils" + "net/http" + + "github.com/go-chi/chi/v5" + "github.com/go-playground/validator/v10" +) + +func Update( + router chi.Router, + validate *validator.Validate, + tagSvc tagsvc.Tag, +) { + router. + With(authmiddleware.Authorize()). + Put("/tag/{tag_id}/update", func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + tagID := chi.URLParam(r, "tag_id") + + if tagID == "" { + response.RespondJsonErrorWithCode( + ctx, + w, + fmt.Errorf("tag id is not provided"), + response.ErrBadRequest.Code, + response.ErrBadRequest.HttpCode, + "tag id is not provided", + ) + return + } + + var spec tagdomain.TagReq + if err := utils.UnmarshalBody(r, &spec); err != nil { + response.RespondJsonErrorWithCode( + ctx, + w, + err, + response.ErrBadRequest.Code, + response.ErrBadRequest.HttpCode, + "failed to unmarshal body", + ) + return + } + + if err := validate.Struct(spec); err != nil { + response.RespondJsonErrorWithCode( + ctx, + w, + err, + response.ErrBadRequest.Code, + response.ErrBadRequest.HttpCode, + err.(validator.ValidationErrors).Error(), + ) + return + } + + if err := tagSvc.Update(tagID, spec); err != nil { + response.RespondJsonErrorWithCode( + ctx, + w, + err, + response.ErrBadRequest.Code, + response.ErrBadRequest.HttpCode, + err.Error(), + ) + return + } + + response.RespondJsonSuccess(ctx, w, struct { + Message string + }{ + Message: "update tag success", + }) + }) +} diff --git a/internal/services/category/delete.go b/internal/services/category/delete.go new file mode 100644 index 0000000..7203de0 --- /dev/null +++ b/internal/services/category/delete.go @@ -0,0 +1,5 @@ +package categorysvc + +func (i *impl) Delete(id string) error { + return i.categoryRepo.Delete(id) +} diff --git a/internal/services/category/impl.go b/internal/services/category/impl.go index 7314470..414a9a5 100644 --- a/internal/services/category/impl.go +++ b/internal/services/category/impl.go @@ -13,6 +13,7 @@ type Category interface { Create(categorydomain.CategoryReq) error GetAll() ([]categorydomain.Category, error) Update(string, categorydomain.CategoryReq) error + Delete(string) error } func New( diff --git a/internal/services/tag/create.go b/internal/services/tag/create.go index 658acb0..d1097cd 100644 --- a/internal/services/tag/create.go +++ b/internal/services/tag/create.go @@ -4,5 +4,5 @@ import tagdomain "legalgo-BE-go/internal/domain/tag" func (i *impl) Create(spec tagdomain.TagReq) error { // return i.tagRepo.Create(spec) - return i.tagRepo.CreateModel(spec) + return i.tagRepo.Create(spec) } diff --git a/internal/services/tag/delete.go b/internal/services/tag/delete.go new file mode 100644 index 0000000..99a0fc3 --- /dev/null +++ b/internal/services/tag/delete.go @@ -0,0 +1,5 @@ +package tagsvc + +func (i *impl) Delete(id string) error { + return i.tagRepo.Delete(id) +} diff --git a/internal/services/tag/impl.go b/internal/services/tag/impl.go index b026eff..f760488 100644 --- a/internal/services/tag/impl.go +++ b/internal/services/tag/impl.go @@ -13,6 +13,8 @@ type Tag interface { Create(tagdomain.TagReq) error GetAll() ([]tagdomain.Tag, error) GetAllModel() ([]tagdomain.Tag, error) + Update(string, tagdomain.TagReq) error + Delete(string) error } func New( diff --git a/internal/services/tag/update.go b/internal/services/tag/update.go new file mode 100644 index 0000000..b2da374 --- /dev/null +++ b/internal/services/tag/update.go @@ -0,0 +1,16 @@ +package tagsvc + +import ( + tagdomain "legalgo-BE-go/internal/domain/tag" + timeutils "legalgo-BE-go/internal/utilities/time_utils" +) + +func (i *impl) Update(id string, spec tagdomain.TagReq) error { + newData := tagdomain.Tag{ + ID: id, + Code: spec.Code, + Name: spec.Name, + UpdatedAt: timeutils.Now(), + } + return i.tagRepo.Update(newData) +}