diff --git a/domain/comment.go b/domain/comment.go new file mode 100644 index 0000000..c7fc18c --- /dev/null +++ b/domain/comment.go @@ -0,0 +1,17 @@ +package domain + +import "time" + +type Comment struct { + ID int + ItemID int + UserID string + Text string + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt *time.Time +} + +type CommentRepository interface { + Create(comment *Comment) error +} diff --git a/domain/errors.go b/domain/errors.go index 686f9c4..bb43cd9 100644 --- a/domain/errors.go +++ b/domain/errors.go @@ -3,7 +3,8 @@ package domain import "errors" var ( - ErrNotFound = errors.New("not found") - ErrInvalidFileType = errors.New("invalid file type: only JPEG and PNG are allowed") - ErrFileTooLarge = errors.New("file too large: max size is 3MB") + ErrNotFound = errors.New("not found") + ErrInvalidFileType = errors.New("invalid file type: only JPEG and PNG are allowed") + ErrFileTooLarge = errors.New("file too large: max size is 3MB") + ErrCommentTextEmpty = errors.New("comment text cannot be empty") ) diff --git a/handler/comment.go b/handler/comment.go new file mode 100644 index 0000000..5ffbecf --- /dev/null +++ b/handler/comment.go @@ -0,0 +1,44 @@ +package handler + +import ( + "net/http" + + "github.com/labstack/echo/v4" + "github.com/traPtitech/booQ-v3/domain" + "github.com/traPtitech/booQ-v3/handler/openapi" +) + +func (h *handler) PostComment(ctx echo.Context, itemId openapi.ItemIdInPath) error { + + var req openapi.PostComment + if err := ctx.Bind(&req); err != nil { + return ctx.JSON(http.StatusBadRequest, err) + } + + // TODO: ミドルウェアからユーザーidを取得するように + userId := "test-user-id" + + comment, err := h.cu.CreateComment(itemId, userId, req.Text) + if err != nil { + if err == domain.ErrItemNotFound { + // Itemがないとき + return ctx.JSON(http.StatusNotFound, "item not found") + } else if err == domain.ErrCommentTextEmpty { + // 投稿されたコメントが空の時 + return ctx.JSON(http.StatusBadRequest, "comment text is empty") + } + + return ctx.JSON(http.StatusInternalServerError, err) + } + + res := openapi.Comment{ + Id: &comment.ID, + ItemId: &comment.ItemID, + UserId: &comment.UserID, + Text: comment.Text, + CreatedAt: &comment.CreatedAt, + UpdatedAt: &comment.UpdatedAt, + } + + return ctx.JSON(http.StatusCreated, res) +} diff --git a/handler/handler.go b/handler/handler.go index ddd65a8..ad28b02 100644 --- a/handler/handler.go +++ b/handler/handler.go @@ -8,13 +8,15 @@ import ( type handler struct { iu usecase.ItemUseCase + cu usecase.CommentUsecase fu usecase.FileUseCase } -func NewHandler(iu usecase.ItemUseCase, fu usecase.FileUseCase) openapi.ServerInterface { +func NewHandler(iu usecase.ItemUseCase, cu usecase.CommentUsecase, fu usecase.FileUseCase) openapi.ServerInterface { return &handler{ iu: iu, fu: fu, + cu: cu, } } @@ -48,11 +50,6 @@ func (h *handler) PostBorrowEquipmentReturn(ctx echo.Context, itemId openapi.Ite panic("implement me") } -func (h *handler) PostComment(ctx echo.Context, itemId openapi.ItemIdInPath) error { - //TODO implement me - panic("implement me") -} - func (h *handler) RemoveLike(ctx echo.Context, itemId openapi.ItemIdInPath) error { //TODO implement me panic("implement me") diff --git a/main.go b/main.go index 9f5a3e1..cd78009 100644 --- a/main.go +++ b/main.go @@ -37,6 +37,7 @@ func main() { // Repository itemRepo := repository.NewItemRepository(db) + commentRepo := repository.NewCommentRepository(db) fileRepo := repository.NewFileRepository(db) // Storage @@ -44,10 +45,11 @@ func main() { // UseCase itemUseCase := usecase.NewItemUseCase(itemRepo) + commentUsecase := usecase.NewCommentUsecase(commentRepo, itemRepo) fileUseCase := usecase.NewFileUseCase(fileRepo, fileStorage) // Handler - h := handler.NewHandler(itemUseCase, fileUseCase) + h := handler.NewHandler(itemUseCase, commentUsecase, fileUseCase) openapi.RegisterHandlers(e, h) e.Logger.Fatal(e.Start(":3001")) diff --git a/repository/comment.go b/repository/comment.go new file mode 100644 index 0000000..894beee --- /dev/null +++ b/repository/comment.go @@ -0,0 +1,43 @@ +package repository + +import ( + "time" + + "github.com/traPtitech/booQ-v3/domain" + "gorm.io/gorm" +) + +type comment struct { + GormModel // ID, CreatedAt, UpdatedAt + ItemID int `gorm:"not null"` + UserID string `gorm:"type:varchar(32);not null"` + Text string `gorm:"column:comment;type:text;not null"` + DeletedAt *time.Time +} + +type commentRepository struct { + db *gorm.DB +} + +func NewCommentRepository(db *gorm.DB) domain.CommentRepository { + return &commentRepository{db: db} +} + +func (r *commentRepository) Create(c *domain.Comment) error { + newComment := &comment{ + ItemID: c.ItemID, + UserID: c.UserID, + Text: c.Text, + } + + if err := r.db.Create(newComment).Error; err != nil { + return err + } + + c.ID = newComment.ID + c.CreatedAt = newComment.CreatedAt + c.UpdatedAt = newComment.UpdatedAt + c.DeletedAt = newComment.DeletedAt + + return nil +} diff --git a/repository/db.go b/repository/db.go index 8194669..f6f1b6d 100644 --- a/repository/db.go +++ b/repository/db.go @@ -14,6 +14,7 @@ import ( var allTables = []interface{}{ item{}, file{}, + comment{}, } type GormModel struct { diff --git a/usecase/comment.go b/usecase/comment.go new file mode 100644 index 0000000..f01dc44 --- /dev/null +++ b/usecase/comment.go @@ -0,0 +1,53 @@ +package usecase + +import ( + "github.com/traPtitech/booQ-v3/domain" +) + +type CommentUsecase interface { + CreateComment( + itemID int, + userID string, + text string, + ) ( + *domain.Comment, error, + ) +} + +type commentUsecase struct { + CommentRepo domain.CommentRepository + ItemRepo domain.ItemRepository +} + +func NewCommentUsecase(commentRepo domain.CommentRepository, ItemRepo domain.ItemRepository) CommentUsecase { + return &commentUsecase{ + CommentRepo: commentRepo, + ItemRepo: ItemRepo, + } +} + +func (u *commentUsecase) CreateComment(itemId int, userId string, text string) (*domain.Comment, error) { + + _, err := u.ItemRepo.GetByID(itemId) + + if err != nil { + return nil, err + } + + if text == "" { + return nil, domain.ErrCommentTextEmpty + } + + comment := &domain.Comment{ + ItemID: itemId, + UserID: userId, + Text: text, + } + + err = u.CommentRepo.Create(comment) + if err != nil { + return nil, err + } + + return comment, nil +}