diff --git a/pkg/api/usecase/wishboard/interactor.go b/pkg/api/usecase/wishboard/interactor.go new file mode 100644 index 0000000..6b202ff --- /dev/null +++ b/pkg/api/usecase/wishboard/interactor.go @@ -0,0 +1,219 @@ +package wishboard + +import ( + "context" + "errors" + "wantum/pkg/domain/entity/wishboard" + "wantum/pkg/domain/repository" + fileservice "wantum/pkg/domain/service/file" + userservice "wantum/pkg/domain/service/user" + wishboardservice "wantum/pkg/domain/service/wishboard" + "wantum/pkg/tlog" + "wantum/pkg/werrors" +) + +type Interactor interface { + CreateNewWishBoard(ctx context.Context, authID, title string, backgroundImage []byte) (*wishboard.Entity, error) + GetMyWishBoards(ctx context.Context, authID string) (wishboard.EntitySlice, error) + UpdateTitle(ctx context.Context, wishBoardID int, title, authID string) error + UpdateBackgroundImage(ctx context.Context, wishBoardID int, backgroundImage []byte, authID string) error + DeleteWishBoard(ctx context.Context, wishBoardID int, authID string) error +} + +type interactor struct { + masterTxManager repository.MasterTxManager + userService userservice.Service + wishBoardService wishboardservice.Service + fileService fileservice.Service +} + +func New(masterTxManager repository.MasterTxManager, userService userservice.Service, wishBoardService wishboardservice.Service, fileService fileservice.Service) Interactor { + return &interactor{ + masterTxManager: masterTxManager, + userService: userService, + wishBoardService: wishBoardService, + fileService: fileService, + } +} + +func (i *interactor) CreateNewWishBoard(ctx context.Context, authID, title string, backgroundImage []byte) (*wishboard.Entity, error) { + if title == "" { + err := errors.New("Error occurred when board title validation.") + tlog.PrintErrorLogWithCtx(ctx, err) + return nil, werrors.FromConstant(err, werrors.BadRequest) + } + + var wishBoardEntity *wishboard.Entity + err := i.masterTxManager.Transaction(ctx, func(ctx context.Context, masterTx repository.MasterTx) error { + userEntity, err := i.userService.GetByAuthID(ctx, masterTx, authID) + if err != nil { + return werrors.Stack(err) + } + + // 背景画像を保存し、URLを取得 + backgroundImageURL, err := i.fileService.UploadImageToLocalFolder(backgroundImage) + if err != nil { + return werrors.Stack(err) + } + + // TODO: 招待URLの自動生成 + inviteURL := "hoge" + + wishBoardEntity, err = i.wishBoardService.Create(ctx, masterTx, title, backgroundImageURL, inviteURL, userEntity.ID) + if err != nil { + return werrors.Stack(err) + } + + return nil + }) + if err != nil { + return nil, werrors.Stack(err) + } + + return wishBoardEntity, nil +} + +func (i *interactor) GetMyWishBoards(ctx context.Context, authID string) (wishboard.EntitySlice, error) { + var wishBoardSlice wishboard.EntitySlice + err := i.masterTxManager.Transaction(ctx, func(ctx context.Context, masterTx repository.MasterTx) error { + userEntity, err := i.userService.GetByAuthID(ctx, masterTx, authID) + if err != nil { + return werrors.Stack(err) + } + + // 自分が所属しているWishBoardのリストを取得 + wishBoardSlice, err = i.wishBoardService.GetMyBoards(ctx, masterTx, userEntity.ID) + if err != nil { + return werrors.Stack(err) + } + + return nil + }) + if err != nil { + return nil, werrors.Stack(err) + } + + return wishBoardSlice, nil +} + +func (i *interactor) UpdateTitle(ctx context.Context, wishBoardID int, title, authID string) error { + if title == "" { + err := errors.New("Error occurred when board title validation.") + tlog.PrintErrorLogWithCtx(ctx, err) + return werrors.FromConstant(err, werrors.BadRequest) + } + + err := i.masterTxManager.Transaction(ctx, func(ctx context.Context, masterTx repository.MasterTx) error { + userEntity, err := i.userService.GetByAuthID(ctx, masterTx, authID) + if err != nil { + return werrors.Stack(err) + } + + // WishBoardが存在するか確認 + wishBoardEntity, err := i.wishBoardService.GetByPK(ctx, masterTx, wishBoardID) + if err != nil { + return werrors.Stack(err) + } + + // ユーザがWishBoardのメンバーでなければPermissionDenied + isMember, err := i.wishBoardService.IsMember(ctx, masterTx, userEntity.ID, wishBoardEntity.ID) + if err != nil { + return werrors.Stack(err) + } + if !isMember { + err := errors.New("Error occurred when update board title. cause: permission denied") + tlog.PrintErrorLogWithCtx(ctx, err) + return werrors.FromConstant(err, werrors.WishBoardPermissionDenied) + } + + if err := i.wishBoardService.UpdateTitle(ctx, masterTx, wishBoardEntity.ID, title); err != nil { + return werrors.Stack(err) + } + return nil + }) + if err != nil { + return werrors.Stack(err) + } + + return nil +} + +func (i *interactor) UpdateBackgroundImage(ctx context.Context, wishBoardID int, backgroundImage []byte, authID string) error { + err := i.masterTxManager.Transaction(ctx, func(ctx context.Context, masterTx repository.MasterTx) error { + userEntity, err := i.userService.GetByAuthID(ctx, masterTx, authID) + if err != nil { + return werrors.Stack(err) + } + + // WishBoardが存在するか確認 + wishBoardEntity, err := i.wishBoardService.GetByPK(ctx, masterTx, wishBoardID) + if err != nil { + return werrors.Stack(err) + } + + // ユーザがWishBoardのメンバーでなければPermissionDenied + isMember, err := i.wishBoardService.IsMember(ctx, masterTx, userEntity.ID, wishBoardEntity.ID) + if err != nil { + return werrors.Stack(err) + } + if !isMember { + err := errors.New("Error occurred when update board background image. cause: permission denied") + tlog.PrintErrorLogWithCtx(ctx, err) + return werrors.FromConstant(err, werrors.WishBoardPermissionDenied) + } + + // 背景画像を保存し、URLを取得 + backgroundImageURL, err := i.fileService.UploadImageToLocalFolder(backgroundImage) + if err != nil { + return werrors.Stack(err) + } + + if err := i.wishBoardService.UpdateBackgroundImageURL(ctx, masterTx, wishBoardEntity.ID, backgroundImageURL); err != nil { + return werrors.Stack(err) + } + + return nil + }) + if err != nil { + return werrors.Stack(err) + } + + return nil +} + +func (i *interactor) DeleteWishBoard(ctx context.Context, wishBoardID int, authID string) error { + err := i.masterTxManager.Transaction(ctx, func(ctx context.Context, masterTx repository.MasterTx) error { + userEntity, err := i.userService.GetByAuthID(ctx, masterTx, authID) + if err != nil { + return werrors.Stack(err) + } + + // WishBoardが存在するか確認 + wishBoardEntity, err := i.wishBoardService.GetByPK(ctx, masterTx, wishBoardID) + if err != nil { + return werrors.Stack(err) + } + + // ユーザがWishBoardのメンバーでなければPermissionDenied + isMember, err := i.wishBoardService.IsMember(ctx, masterTx, userEntity.ID, wishBoardEntity.ID) + if err != nil { + return werrors.Stack(err) + } + if !isMember { + err := errors.New("Error occurred when delete board. cause: permission denied") + tlog.PrintErrorLogWithCtx(ctx, err) + return werrors.FromConstant(err, werrors.WishBoardPermissionDenied) + } + + if err := i.wishBoardService.Delete(ctx, masterTx, wishBoardEntity.ID); err != nil { + return werrors.Stack(err) + } + + return nil + }) + if err != nil { + return werrors.Stack(err) + } + + return nil +} diff --git a/pkg/domain/entity/wishboard/entity.go b/pkg/domain/entity/wishboard/entity.go new file mode 100644 index 0000000..a44ac3a --- /dev/null +++ b/pkg/domain/entity/wishboard/entity.go @@ -0,0 +1,17 @@ +package wishboard + +import "time" + +type Entity struct { + ID int + Title string + BackgroundImageURL string + InviteURL string + UserID int + CreatedAt *time.Time + UpdatedAt *time.Time + DeletedAt *time.Time + // WishCategories +} + +type EntitySlice []*Entity diff --git a/pkg/domain/repository/userwishboard/repository.go b/pkg/domain/repository/userwishboard/repository.go new file mode 100644 index 0000000..15d2ca8 --- /dev/null +++ b/pkg/domain/repository/userwishboard/repository.go @@ -0,0 +1,13 @@ +package userwishboard + +import ( + "context" + "wantum/pkg/domain/repository" +) + +type Repository interface { + Insert(ctx context.Context, masterTx repository.MasterTx, userID, wishBoardID int) error + Exists(ctx context.Context, masterTx repository.MasterTx, userID, wishBoardID int) (bool, error) + SelectWishBoardIDsByUserID(ctx context.Context, masterTx repository.MasterTx, userID int) ([]int, error) + Delete(ctx context.Context, masterTx repository.MasterTx, userID, wishBoardID int) error +} diff --git a/pkg/domain/repository/wishboard/repository.go b/pkg/domain/repository/wishboard/repository.go new file mode 100644 index 0000000..0b09872 --- /dev/null +++ b/pkg/domain/repository/wishboard/repository.go @@ -0,0 +1,17 @@ +package wishboard + +import ( + "context" + "time" + "wantum/pkg/domain/entity/wishboard" + "wantum/pkg/domain/repository" +) + +type Repository interface { + Insert(ctx context.Context, masterTx repository.MasterTx, wishBoardEntity *wishboard.Entity) (*wishboard.Entity, error) + SelectByPK(ctx context.Context, masterTx repository.MasterTx, wishBoardID int) (*wishboard.Entity, error) + SelectByPKs(ctx context.Context, masterTx repository.MasterTx, wishBoardIDs []int) (wishboard.EntitySlice, error) + UpdateTitle(ctx context.Context, masterTx repository.MasterTx, wishBoardID int, title string, updatedAt *time.Time) error + UpdateBackgroundImageURL(ctx context.Context, masterTx repository.MasterTx, wishBoardID int, backgroundImageURL string, updatedAt *time.Time) error + Delete(ctx context.Context, masterTx repository.MasterTx, wishBoardEntity *wishboard.Entity) error +} diff --git a/pkg/domain/service/wishboard/service.go b/pkg/domain/service/wishboard/service.go new file mode 100644 index 0000000..ffe6da9 --- /dev/null +++ b/pkg/domain/service/wishboard/service.go @@ -0,0 +1,124 @@ +package wishboard + +import ( + "context" + "time" + "wantum/pkg/domain/entity/wishboard" + "wantum/pkg/domain/repository" + userwishboardrepository "wantum/pkg/domain/repository/userwishboard" + wishboardrepository "wantum/pkg/domain/repository/wishboard" + "wantum/pkg/werrors" +) + +type Service interface { + Create(ctx context.Context, masterTx repository.MasterTx, title, backgroundImageURL, inviteURL string, userID int) (*wishboard.Entity, error) + GetByPK(ctx context.Context, masterTx repository.MasterTx, wishBoardID int) (*wishboard.Entity, error) + GetMyBoards(ctx context.Context, masterTx repository.MasterTx, userID int) (wishboard.EntitySlice, error) + IsMember(ctx context.Context, masterTx repository.MasterTx, userID, wishBoardID int) (bool, error) + UpdateTitle(ctx context.Context, masterTx repository.MasterTx, wishBoardID int, title string) error + UpdateBackgroundImageURL(ctx context.Context, masterTx repository.MasterTx, wishBoardID int, backgroundImageURL string) error + Delete(ctx context.Context, masterTx repository.MasterTx, wishBoardID int) error +} + +type service struct { + wishBoardRepository wishboardrepository.Repository + userWishBoardRepository userwishboardrepository.Repository +} + +func New(wishBoardRepository wishboardrepository.Repository, userWishBoardRepository userwishboardrepository.Repository) Service { + return &service{ + wishBoardRepository: wishBoardRepository, + userWishBoardRepository: userWishBoardRepository, + } +} + +func (s *service) Create(ctx context.Context, masterTx repository.MasterTx, title, backgroundImageURL, inviteURL string, userID int) (*wishboard.Entity, error) { + now := time.Now() + + newWishBoard := &wishboard.Entity{ + Title: title, + BackgroundImageURL: backgroundImageURL, + InviteURL: inviteURL, + UserID: userID, + CreatedAt: &now, + UpdatedAt: &now, + } + + createdWishBoard, err := s.wishBoardRepository.Insert(ctx, masterTx, newWishBoard) + if err != nil { + return nil, werrors.Stack(err) + } + + if err := s.userWishBoardRepository.Insert(ctx, masterTx, userID, createdWishBoard.ID); err != nil { + return nil, werrors.Stack(err) + } + + return createdWishBoard, nil +} + +func (s *service) GetByPK(ctx context.Context, masterTx repository.MasterTx, wishBoardID int) (*wishboard.Entity, error) { + wishBoardEntity, err := s.wishBoardRepository.SelectByPK(ctx, masterTx, wishBoardID) + if err != nil { + return nil, werrors.Stack(err) + } + return wishBoardEntity, nil +} + +func (s *service) GetMyBoards(ctx context.Context, masterTx repository.MasterTx, userID int) (wishboard.EntitySlice, error) { + wishBoardIDs, err := s.userWishBoardRepository.SelectWishBoardIDsByUserID(ctx, masterTx, userID) + if err != nil { + return nil, werrors.Stack(err) + } + + if len(wishBoardIDs) == 0 { + return nil, nil + } + + wishBoardSlice, err := s.wishBoardRepository.SelectByPKs(ctx, masterTx, wishBoardIDs) + if err != nil { + return nil, werrors.Stack(err) + } + + return wishBoardSlice, nil +} + +func (s *service) IsMember(ctx context.Context, masterTx repository.MasterTx, userID, wishBoardID int) (bool, error) { + exists, err := s.userWishBoardRepository.Exists(ctx, masterTx, userID, wishBoardID) + if err != nil { + return false, werrors.Stack(err) + } + return exists, nil +} + +func (s *service) UpdateTitle(ctx context.Context, masterTx repository.MasterTx, wishBoardID int, title string) error { + now := time.Now() + + if err := s.wishBoardRepository.UpdateTitle(ctx, masterTx, wishBoardID, title, &now); err != nil { + return werrors.Stack(err) + } + return nil +} + +func (s *service) UpdateBackgroundImageURL(ctx context.Context, masterTx repository.MasterTx, wishBoardID int, backgroundImageURL string) error { + now := time.Now() + + if err := s.wishBoardRepository.UpdateBackgroundImageURL(ctx, masterTx, wishBoardID, backgroundImageURL, &now); err != nil { + return werrors.Stack(err) + } + return nil +} + +func (s *service) Delete(ctx context.Context, masterTx repository.MasterTx, wishBoardID int) error { + now := time.Now() + + wishBoardEntity := &wishboard.Entity{ + ID: wishBoardID, + UpdatedAt: &now, + DeletedAt: &now, + } + + if err := s.wishBoardRepository.Delete(ctx, masterTx, wishBoardEntity); err != nil { + return werrors.Stack(err) + } + return nil +} diff --git a/pkg/infrastructure/mysql/userwishboard/repository.go b/pkg/infrastructure/mysql/userwishboard/repository.go new file mode 100644 index 0000000..dbfa185 --- /dev/null +++ b/pkg/infrastructure/mysql/userwishboard/repository.go @@ -0,0 +1,114 @@ +package userwishboard + +import ( + "context" + "database/sql" + "wantum/pkg/domain/repository" + "wantum/pkg/domain/repository/userwishboard" + "wantum/pkg/infrastructure/mysql" + "wantum/pkg/tlog" + "wantum/pkg/werrors" +) + +type repositoryImpliment struct { + masterTxManager repository.MasterTxManager +} + +func New(masterTxManager repository.MasterTxManager) userwishboard.Repository { + return &repositoryImpliment{ + masterTxManager: masterTxManager, + } +} + +func (r *repositoryImpliment) Insert(ctx context.Context, masterTx repository.MasterTx, userID, wishBoardID int) error { + tx, err := mysql.ExtractTx(masterTx) + if err != nil { + tlog.PrintErrorLogWithCtx(ctx, err) + return werrors.FromConstant(err, werrors.ServerError) + } + + _, err = tx.Exec(` + INSERT INTO users_wish_boards( + user_id, wish_board_id + ) VALUES (?, ?) + `, userID, wishBoardID) + if err != nil { + tlog.PrintErrorLogWithCtx(ctx, err) + return werrors.FromConstant(err, werrors.ServerError) + } + + return nil +} + +func (r *repositoryImpliment) Exists(ctx context.Context, masterTx repository.MasterTx, userID, wishBoardID int) (bool, error) { + tx, err := mysql.ExtractTx(masterTx) + if err != nil { + tlog.PrintErrorLogWithCtx(ctx, err) + return false, werrors.FromConstant(err, werrors.ServerError) + } + + row := tx.QueryRow(` + SELECT EXISTS ( + SELECT * FROM users_wish_boards WHERE user_id = ? AND wish_board_id = ? + ) + `, userID, wishBoardID) + + var exists bool + err = row.Scan(&exists) + if err != nil { + return false, werrors.FromConstant(err, werrors.ServerError) + } + + return exists, nil +} + +func (r *repositoryImpliment) SelectWishBoardIDsByUserID(ctx context.Context, masterTx repository.MasterTx, userID int) ([]int, error) { + tx, err := mysql.ExtractTx(masterTx) + if err != nil { + tlog.PrintErrorLogWithCtx(ctx, err) + return nil, werrors.FromConstant(err, werrors.ServerError) + } + + rows, err := tx.Query(` + SELECT wish_board_id FROM users_wish_boards WHERE user_id = ? + `, userID) + if err != nil { + if err == sql.ErrNoRows { + return nil, nil + } + return nil, werrors.FromConstant(err, werrors.ServerError) + } + + wishBoardIDSlice := []int{} + for rows.Next() { + var wishBoardID int + if err := rows.Scan(&wishBoardID); err != nil { + if err == sql.ErrNoRows { + return nil, nil + } + return nil, werrors.FromConstant(err, werrors.ServerError) + } + + wishBoardIDSlice = append(wishBoardIDSlice, wishBoardID) + } + + return wishBoardIDSlice, nil +} + +func (r *repositoryImpliment) Delete(ctx context.Context, masterTx repository.MasterTx, userID, wishBoardID int) error { + tx, err := mysql.ExtractTx(masterTx) + if err != nil { + tlog.PrintErrorLogWithCtx(ctx, err) + return werrors.FromConstant(err, werrors.ServerError) + } + + _, err = tx.Exec(` + DELETE FROM users_wish_boards WHERE user_id = ? AND wish_board_id = ? + `, userID, wishBoardID) + if err != nil { + tlog.PrintErrorLogWithCtx(ctx, err) + return werrors.FromConstant(err, werrors.ServerError) + } + + return nil +} diff --git a/pkg/infrastructure/mysql/wishboard/repository.go b/pkg/infrastructure/mysql/wishboard/repository.go new file mode 100644 index 0000000..4ee7ecf --- /dev/null +++ b/pkg/infrastructure/mysql/wishboard/repository.go @@ -0,0 +1,203 @@ +package wishboard + +import ( + "bytes" + "context" + "database/sql" + "strconv" + "time" + "wantum/pkg/domain/entity/wishboard" + "wantum/pkg/domain/repository" + wishboardrepository "wantum/pkg/domain/repository/wishboard" + "wantum/pkg/infrastructure/mysql" + "wantum/pkg/tlog" + "wantum/pkg/werrors" +) + +type repositoryImpliment struct { + masterTxManager repository.MasterTxManager +} + +func New(masterTxManager repository.MasterTxManager) wishboardrepository.Repository { + return &repositoryImpliment{ + masterTxManager: masterTxManager, + } +} + +func (r *repositoryImpliment) Insert(ctx context.Context, masterTx repository.MasterTx, wishBoardEntity *wishboard.Entity) (*wishboard.Entity, error) { + tx, err := mysql.ExtractTx(masterTx) + if err != nil { + tlog.PrintErrorLogWithCtx(ctx, err) + return nil, werrors.FromConstant(err, werrors.ServerError) + } + + // CreatedAt, UpdatedAtの実体を渡す + result, err := tx.Exec(` + INSERT INTO wish_boards( + title, background_image_url, invite_url, user_id, created_at, updated_at + ) VALUES (?, ?, ?, ?, ?, ?) + `, wishBoardEntity.Title, wishBoardEntity.BackgroundImageURL, wishBoardEntity.InviteURL, wishBoardEntity.UserID, *wishBoardEntity.CreatedAt, *wishBoardEntity.UpdatedAt) + if err != nil { + tlog.PrintErrorLogWithCtx(ctx, err) + return nil, werrors.FromConstant(err, werrors.ServerError) + } + + insertID, err := result.LastInsertId() + if err != nil { + tlog.PrintErrorLogWithCtx(ctx, err) + return nil, werrors.FromConstant(err, werrors.ServerError) + } + + wishBoardEntity.ID = int(insertID) + + return wishBoardEntity, nil +} + +func (r *repositoryImpliment) SelectByPK(ctx context.Context, masterTx repository.MasterTx, wishBoardID int) (*wishboard.Entity, error) { + tx, err := mysql.ExtractTx(masterTx) + if err != nil { + tlog.PrintErrorLogWithCtx(ctx, err) + return nil, werrors.FromConstant(err, werrors.ServerError) + } + + row := tx.QueryRow(` + SELECT + id, title, background_image_url, invite_url, user_id, created_at, updated_at + FROM wish_boards + WHERE id = ? AND deleted_at IS NULL + `, wishBoardID) + + // ポインタ型のフィールドについては、あらかじめメモリ確保する + wishBoardEntity := wishboard.Entity{CreatedAt: &time.Time{}, UpdatedAt: &time.Time{}} + // CreatedAt, UpdatedAtはポインタなので「&」はつけずにそのまま渡す + err = row.Scan( + &wishBoardEntity.ID, &wishBoardEntity.Title, &wishBoardEntity.BackgroundImageURL, &wishBoardEntity.InviteURL, &wishBoardEntity.UserID, wishBoardEntity.CreatedAt, wishBoardEntity.UpdatedAt) + + if err != nil { + if err == sql.ErrNoRows { + return nil, werrors.FromConstant(err, werrors.WishBoardNotFound) + } + return nil, werrors.FromConstant(err, werrors.ServerError) + } + + return &wishBoardEntity, nil +} + +func (r *repositoryImpliment) SelectByPKs(ctx context.Context, masterTx repository.MasterTx, wishBoardIDs []int) (wishboard.EntitySlice, error) { + tx, err := mysql.ExtractTx(masterTx) + if err != nil { + tlog.PrintErrorLogWithCtx(ctx, err) + return nil, werrors.FromConstant(err, werrors.ServerError) + } + + // IDのリストからSQL文のIN句用の文字列を作成 + var buf bytes.Buffer + for i, wishBoardID := range wishBoardIDs { + if i == 0 { + buf.WriteString(strconv.Itoa(wishBoardID)) + } else { + buf.WriteString(",") + buf.WriteString(strconv.Itoa(wishBoardID)) + } + } + + rows, err := tx.Query(` + SELECT + id, title, background_image_url, invite_url, user_id, created_at, updated_at + FROM wish_boards + WHERE id IN (` + buf.String() + + `) AND deleted_at IS NULL + `) + if err != nil { + if err == sql.ErrNoRows { + return nil, werrors.FromConstant(err, werrors.WishBoardNotFound) + } + return nil, werrors.FromConstant(err, werrors.ServerError) + } + + wishBoardSlice := wishboard.EntitySlice{} + for rows.Next() { + // ポインタ型のフィールドについては、あらかじめメモリ確保する + wishBoardEntity := wishboard.Entity{CreatedAt: &time.Time{}, UpdatedAt: &time.Time{}} + // CreatedAt, UpdatedAtはポインタなので「&」はつけずにそのまま渡す + err := rows.Scan( + &wishBoardEntity.ID, &wishBoardEntity.Title, &wishBoardEntity.BackgroundImageURL, &wishBoardEntity.InviteURL, &wishBoardEntity.UserID, wishBoardEntity.CreatedAt, wishBoardEntity.UpdatedAt) + + if err != nil { + if err == sql.ErrNoRows { + return nil, werrors.FromConstant(err, werrors.WishBoardNotFound) + } + return nil, werrors.FromConstant(err, werrors.ServerError) + } + + wishBoardSlice = append(wishBoardSlice, &wishBoardEntity) + } + + return wishBoardSlice, nil +} + +func (r *repositoryImpliment) UpdateTitle(ctx context.Context, masterTx repository.MasterTx, wishBoardID int, title string, updatedAt *time.Time) error { + tx, err := mysql.ExtractTx(masterTx) + if err != nil { + tlog.PrintErrorLogWithCtx(ctx, err) + return werrors.FromConstant(err, werrors.ServerError) + } + + // UpdatedAtの実体を渡す + _, err = tx.Exec(` + UPDATE wish_boards SET + title=?, + updated_at=? + WHERE id = ? + `, title, *updatedAt, wishBoardID) + if err != nil { + tlog.PrintErrorLogWithCtx(ctx, err) + return werrors.FromConstant(err, werrors.ServerError) + } + + return nil +} + +func (r *repositoryImpliment) UpdateBackgroundImageURL(ctx context.Context, masterTx repository.MasterTx, wishBoardID int, backgroundImageURL string, updatedAt *time.Time) error { + tx, err := mysql.ExtractTx(masterTx) + if err != nil { + tlog.PrintErrorLogWithCtx(ctx, err) + return werrors.FromConstant(err, werrors.ServerError) + } + + // UpdatedAtの実体を渡す + _, err = tx.Exec(` + UPDATE wish_boards SET + background_image_url=?, + updated_at=? + WHERE id = ? + `, backgroundImageURL, *updatedAt, wishBoardID) + if err != nil { + tlog.PrintErrorLogWithCtx(ctx, err) + return werrors.FromConstant(err, werrors.ServerError) + } + + return nil +} + +func (r *repositoryImpliment) Delete(ctx context.Context, masterTx repository.MasterTx, wishBoardEntity *wishboard.Entity) error { + tx, err := mysql.ExtractTx(masterTx) + if err != nil { + tlog.PrintErrorLogWithCtx(ctx, err) + return werrors.FromConstant(err, werrors.ServerError) + } + + // UpdatedAt, DeletedAtの実体を渡す + _, err = tx.Exec(` + UPDATE wish_boards SET + updated_at=?, + deleted_at=? + WHERE id = ? + `, *wishBoardEntity.UpdatedAt, *wishBoardEntity.DeletedAt, wishBoardEntity.ID) + if err != nil { + tlog.PrintErrorLogWithCtx(ctx, err) + return werrors.FromConstant(err, werrors.ServerError) + } + + return nil +} diff --git a/pkg/werrors/constants.go b/pkg/werrors/constants.go index ac5cc5b..cb27ed7 100644 --- a/pkg/werrors/constants.go +++ b/pkg/werrors/constants.go @@ -25,6 +25,18 @@ var ( ErrorMessageJP: "リクエストされたユーザーはすでに削除されている可能性があります", ErrorMessageEN: "requested user is not found", } + WishBoardNotFound = &WantumError{ + GrpcErrorCode: codes.NotFound, + ErrorCode: http.StatusNotFound, + ErrorMessageJP: "ボードは既に削除された可能性があります", + ErrorMessageEN: "requested wish_board is not found", + } + WishBoardPermissionDenied = &WantumError{ + GrpcErrorCode: codes.PermissionDenied, + ErrorCode: http.StatusForbidden, + ErrorMessageJP: "ボードへのアクセスが許可されていません", + ErrorMessageEN: "you don't have access to wish_board", + } BadRequest = &WantumError{ GrpcErrorCode: codes.InvalidArgument, ErrorCode: http.StatusBadRequest,