Skip to content

Feat/wakape/create sponsorship activity#1062

Open
Wakai111 wants to merge 7 commits intodevelopfrom
feat/wakape/create-sponsorship-activity
Open

Feat/wakape/create sponsorship activity#1062
Wakai111 wants to merge 7 commits intodevelopfrom
feat/wakape/create-sponsorship-activity

Conversation

@Wakai111
Copy link
Collaborator

@Wakai111 Wakai111 commented Mar 7, 2026

対応Issue

概要

協賛活動の「新規作成(POST)」と「詳細取得(GET ID)」のAPIを実装しました。

  • POST /sponsorship_activities:活動本体とプラン紐付け(中間テーブル)を安全に一括登録する処理を実装
  • GET /sponsorship_activities/{id}:ID指定による詳細取得を実装

画面スクリーンショット等

バックエンドのAPI実装のため、画面の変更はありません。

テスト項目

  • 概ね、設計書通りに実装できていること
  • POST /sponsorship_activities を実行し、レスポンスが正常に返ってくること
  • DBを確認し、sponsorship_activitiesactivity_sponsor_style_links の両方に正しくデータが保存されていること
  • 作成時に取得したIDを用いて GET /sponsorship_activities/{id} を実行し、作成したデータが正しく取得できること

備考

本PRがマージされたあとに、この実装に依存した「更新・削除(PUT/DELETE)」のPRを提出予定です。

@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

このプルリクエストは、協賛活動を管理するための新しいAPIエンドポイントを導入します。これにより、新しい協賛活動とその関連する協賛スタイルを単一のトランザクション操作で作成できるようになり、また特定の活動の詳細情報を取得する機能も提供されます。これらの変更は、今後の更新および削除機能の開発の基盤を築くものです。

Highlights

  • 協賛活動の新規作成API: 協賛活動の新規作成(POST /sponsorship_activities)APIを実装しました。これにより、活動本体と関連するプランの紐付けをトランザクション内で一括登録できます。
  • 協賛活動の詳細取得API: 特定の協賛活動の詳細取得(GET /sponsorship_activities/{id})APIを実装しました。これにより、IDを指定して活動の詳細情報と紐付けられたプラン情報を取得できます。
  • リポジトリ層のトランザクション対応: リポジトリ層にトランザクション開始 (Begin)、トランザクション対応の作成 (Create)、およびプラン紐付け作成 (CreateStyleLink) メソッドを追加し、データの一貫性を確保しました。
  • ユースケース層のロジック追加: ユースケース層で、新規作成時に活動ステータス、実現可能性ステータス、デザイン進捗のデフォルト値を設定するロジックを追加しました。
Changelog
  • api/externals/handler/sponsorship_activity_handler.go
    • PostSponsorshipActivities:モック応答を、リクエストのバインディング、バリデーション、ユースケースの呼び出し、および応答変換を含む協賛活動作成の実際のロジックに置き換えました。
    • GetSponsorshipActivitiesId:モック応答を、ユースケースの呼び出し、未検出時のエラー処理、および応答変換を含むIDによる協賛活動詳細取得の実際のロジックに置き換えました。
  • api/externals/repository/sponsorship_activity_repository.go
    • SponsorshipActivityRepository インターフェース:Find を FindByID に変更し、Create メソッドをトランザクション (*sql.Tx) を受け入れるように変更しました。また、トランザクションを開始するための Begin メソッドと、協賛スタイルリンクを作成するための CreateStyleLink メソッドを追加しました。
    • FindByID:IDに基づいて単一の協賛活動(関連するスポンサーとユーザーの詳細を含む)を取得するロジックを実装しました。
    • Begin:新しいSQLトランザクションを開始するメソッドを実装しました。
    • Create:トランザクション内で新しい協賛活動をデータベースに挿入するロジックを実装しました。
    • CreateStyleLink:トランザクション内で新しい協賛スタイルリンクをデータベースに挿入するロジックを実装しました。
  • api/internals/domain/sponsorship_activity.go
    • POST リクエストボディ用の CreateSponsorshipActivityRequest 構造体(SponsorStyleDetails を含む)を追加しました。
    • リクエスト内の個々の協賛スタイル詳細用の CreateSponsorStyleRequest 構造体を追加しました。
  • api/internals/usecase/sponsorship_activity_usecase.go
    • SponsorshipActivityUseCase インターフェース:CreateSponsorshipActivity メソッドが domain.CreateSponsorshipActivityRequest を受け入れるように変更しました。
    • GetSponsorshipActivityByID:活動に関連する協賛スタイルを取得するように更新しました。
    • CreateSponsorshipActivity:協賛活動とその関連する協賛スタイルをトランザクションで作成するロジックを実装しました。これには、デフォルト値の割り当て、データマッピング、トランザクション管理(開始、コミット、ロールバック)、およびリポジトリメソッドの呼び出しが含まれます。
Activity
  • このプルリクエストには、現時点でのレビュー活動やコメントはありません。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements new APIs for creating (POST) and retrieving (GET by ID) sponsorship activities. However, it introduces a critical security vulnerability due to a lack of essential authorization checks; the POST endpoint allows creating activities for any user, and the GET endpoint allows viewing any activity by ID without verifying ownership or permissions, which could lead to unauthorized data access and manipulation. Additionally, several improvements are suggested, including enhancing error handling in the GetSponsorshipActivitiesId handler, optimizing SQL query execution in the FindByID repository method, constantizing hardcoded strings in the CreateSponsorshipActivity use case, and removing development comments.

@Wakai111 Wakai111 force-pushed the feat/wakape/create-sponsorship-activity branch from f7e8766 to 692ab9c Compare March 7, 2026 15:21
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Mar 7, 2026

Deploying finansu with  Cloudflare Pages  Cloudflare Pages

Latest commit: f616f3f
Status: ✅  Deploy successful!
Preview URL: https://1c518f4b.finansu.pages.dev
Branch Preview URL: https://feat-wakape-create-sponsorsh.finansu.pages.dev

View logs

@Chikuwa0141 Chikuwa0141 self-requested a review March 9, 2026 01:51
Copy link
Collaborator

@hikahana hikahana left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generatedしてるんだからそれを使ってください。
変数命名長くても良いのでわかりやすくしてください。読みづらいです。
aiに書かせるのはいいですが、あなたがこのコードを理解してください。生成aiに全て書かせたように見えますがどうですか?

Comment on lines +42 to +58
// リクエスト用
type CreateSponsorshipActivityRequest struct {
YearPeriodsID int `json:"yearPeriodsId"`
SponsorID int `json:"sponsorId"`
UserID int `json:"userId"`
ActivityStatus string `json:"activityStatus"`
FeasibilityStatus string `json:"feasibilityStatus"`
DesignProgress string `json:"designProgress"`
Remarks string `json:"remarks"`
SponsorStyleDetails []CreateSponsorStyleRequest `json:"sponsorStyleDetails"`
}

// リクエスト用
type CreateSponsorStyleRequest struct {
SponsorStyleID int `json:"sponsorStyleId"`
Category string `json:"category"`
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[ask]
openapiで定義してると思うんだけどなんでこれを使わないでdomainに書いたの?
意図ありですか?

CreateSponsorshipActivityRequest:

type CreateSponsorshipActivityRequest struct {

return u.repo.Find(ctx, id)
}
// 基本データを取得
activity, err := u.repo.FindByID(ctx, id)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[must]
変数命名に関しては、activityだけだとなんのか分からんから↓みたいまで具体的に書いてほしい。
SponsorshipActivityByID

Comment on lines +76 to +78
if req.YearPeriodsID == 0 || req.SponsorID == 0 || req.UserID == 0 {
return echo.NewHTTPError(http.StatusBadRequest, "必須項目(年度期間ID、企業ID、担当者ID)が不足しています。")
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[must]
openapi_genだとポインタで定義になるから==0ではなくて
=! nilのようにnilでないことで必須チェックになると思う。
で、必須チェックするのはyearPeriodsIdとUserIdだけだと思う。

	// SponsorStyleDetails 登録したい協賛プラン情報のリスト
	SponsorStyleDetails *[]struct {
		Category       *CreateSponsorshipActivityRequestSponsorStyleDetailsCategory `json:"category,omitempty"`
		SponsorStyleId *int                                                         `json:"sponsorStyleId,omitempty"`
	} `json:"sponsorStyleDetails,omitempty"`
	UserId        int `json:"userId"`
	YearPeriodsId int `json:"yearPeriodsId"`

}

// 登録処理(ユースケースの呼び出し)
createdActivity, err := h.sponsorshipActivityUseCase.CreateSponsorshipActivity(c.Request().Context(), req)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
createdActivity, err := h.sponsorshipActivityUseCase.CreateSponsorshipActivity(c.Request().Context(), req)
CreateSponsorshipActivity, err := h.sponsorshipActivityUseCase.CreateSponsorshipActivity(c.Request().Context(), req)

func (h *Handler) PostSponsorshipActivities(c echo.Context) error {
return c.String(http.StatusOK, "PostSponsorshipActivities: Mock Response")
// リクエストボディを受け取るための構造体を用意
var req domain.CreateSponsorshipActivityRequest
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var req domain.CreateSponsorshipActivityRequest
var createSponsorshipActivityRequest generated.CreateSponsorshipActivityRequest

とかで命名して欲しい。reqは避けてほしい何なのか分からないから

func (u *sponsorshipActivityUseCase) CreateSponsorshipActivity(ctx context.Context, activity domain.SponsorshipActivity) (domain.SponsorshipActivity, error) {
u.repo.Create(ctx, activity)
// プラン一覧を取得
styles, err := u.repo.GetStyleDetailsByActivityIDs(ctx, []int{id})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
styles, err := u.repo.GetStyleDetailsByActivityIDs(ctx, []int{id})
sponsorStyleDetailsStyle, err := u.repo.GetSponsorStyleDetailsByActivityIDs(ctx, []int{id})

Comment on lines +83 to +92
// 未着手の補完
if req.ActivityStatus == "" {
req.ActivityStatus = string(generated.ActivityStatusUnstarted)
}
if req.FeasibilityStatus == "" {
req.FeasibilityStatus = string(generated.Unstarted)
}
if req.DesignProgress == "" {
req.DesignProgress = string(generated.DesignProgressUnstarted)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[ask]
ここ補完処理をしていると思うんだけど、openapiの定義では必須にしている。
必須にしているなら空ならhandlerの段階でバリデーションで弾かれるからこの処理がされることはないと思うので不要だと思う。
けど、最初の設計としてはどう考えていたの?何もなければ未着手にしたい?
どっちの責務にしたい?クライアント側の責務にするならこれは不要で。サーバー側のせきむにするならrequiredを外してサーバー側にデフォルト値を入れるとかになると思う。

   CreateSponsorshipActivityRequest:
      type: object
      description: 新規作成時のリクエストボディ
      required:
        - yearPeriodsId
        - sponsorId
        - userId
        - activityStatus
        - feasibilityStatus
        - designProgress
      properties:
        yearPeriodsId:
          type: integer
          example: 5
        sponsorId:
          type: integer
          example: 101
        userId:
          type: integer
          example: 5
        activityStatus:
          $ref: "#/components/schemas/ActivityStatus"
        feasibilityStatus:
          $ref: "#/components/schemas/FeasibilityStatus"
        designProgress:
          $ref: "#/components/schemas/DesignProgress"

}

// トランザクション開始
tx, err := u.repo.Begin(ctx)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これはそれ用のrepoがあるからそっちにして

return domain.SponsorshipActivity{}, err
}

defer tx.Rollback()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rollbackもあった気がする

}

// コミット
if err := tx.Commit(); err != nil {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commitもある

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants