Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions api/externals/controller/cmapus_donation_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ type campusDonationController struct {
type CampusDonationController interface {
IndexCampusDonationByFloor(echo.Context) error
IndexCampusDonationBuildingByPeriod(echo.Context) error
CreateCampusDonation(echo.Context) error
UpdateCampusDonation(echo.Context) error
}

func NewCampusDonationController(u usecase.CampusDonationUseCase) CampusDonationController {
Expand Down Expand Up @@ -46,3 +48,69 @@ func (f *campusDonationController) IndexCampusDonationBuildingByPeriod(c echo.Co
}
return c.JSON(http.StatusOK, fundInformationBuildingByPeriod)
}

func (f *campusDonationController) CreateCampusDonation(c echo.Context) error {
ctx := c.Request().Context()
userId := c.QueryParam("user_id")
teacherId := c.QueryParam("teacher_id")
price := c.QueryParam("price")
receivedAt := c.QueryParam("received_at")
yearId := c.QueryParam("year_id")

if userId == "" {
return c.String(http.StatusBadRequest, "user_id is required")
}
if teacherId == "" {
return c.String(http.StatusBadRequest, "teacher_id is required")
}
if price == "" {
return c.String(http.StatusBadRequest, "price is required")
}
if receivedAt == "" {
return c.String(http.StatusBadRequest, "received_at is required")
}
if yearId == "" {
return c.String(http.StatusBadRequest, "year_id is required")
}

err := f.u.CreateCampusDonation(ctx, userId, teacherId, price, receivedAt, yearId)
if err != nil {
return err
}
return c.NoContent(http.StatusCreated)
}
Comment on lines +52 to +81
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

The CreateCampusDonation method is reading parameters from query parameters using c.QueryParam instead of from the JSON request body using c.Bind. According to the OpenAPI specification, this endpoint expects a JSON request body (application/json with schema postRequestBodyCampusDonation), not query parameters.

This is inconsistent with the OpenAPI specification and with other controllers in the codebase (e.g., activity_controller.go, receipt_controller.go) which use c.Bind to parse JSON request bodies for POST requests.

The method should bind the JSON request body to a struct (generated.PostRequestBodyCampusDonation) and extract the values from there.

Copilot uses AI. Check for mistakes.

func (f *campusDonationController) UpdateCampusDonation(c echo.Context) error {
ctx := c.Request().Context()
id := c.QueryParam("id")
userId := c.QueryParam("user_id")
teacherId := c.QueryParam("teacher_id")
price := c.QueryParam("price")
receivedAt := c.QueryParam("received_at")
yearId := c.QueryParam("year_id")

if id == "" {
return c.String(http.StatusBadRequest, "id is required")
}
if userId == "" {
return c.String(http.StatusBadRequest, "user_id is required")
}
if teacherId == "" {
return c.String(http.StatusBadRequest, "teacher_id is required")
}
if price == "" {
return c.String(http.StatusBadRequest, "price is required")
}
if receivedAt == "" {
return c.String(http.StatusBadRequest, "received_at is required")
}
if yearId == "" {
return c.String(http.StatusBadRequest, "year_id is required")
}

err := f.u.UpdateCampusDonation(ctx, id, userId, teacherId, price, receivedAt, yearId)
if err != nil {
return err
}
return c.NoContent(http.StatusOK)
}
Comment on lines +83 to +116
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

The UpdateCampusDonation method is reading parameters from query parameters using c.QueryParam instead of from the JSON request body using c.Bind. According to the OpenAPI specification, this endpoint expects a JSON request body (application/json with schema putRequestBodyCampusDonation), not query parameters.

Additionally, the id parameter should be read from the path parameter using c.Param("id") as defined in the route "/campus_donations/:id", not from query parameters.

This is inconsistent with the OpenAPI specification and with other controllers in the codebase (e.g., activity_controller.go line 68) which use c.Bind to parse JSON request bodies and c.Param for path parameters in PUT requests.

Copilot uses AI. Check for mistakes.
34 changes: 34 additions & 0 deletions api/externals/repository/campus_donation_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ type campusDonationRepository struct {
type CampusDonationRepository interface {
AllCampusDonationByFloor(context.Context, string, string) (*sql.Rows, error)
AllBuildingsByPeriod(context.Context, string) (*sql.Rows, error)
CreateCampusDonation(context.Context, string, string, string, string, string) error
UpdateCampusDonation(context.Context, string, string, string, string, string, string) error
}

func NewCampusDonationRepository(c db.Client, ac abstract.Crud) CampusDonationRepository {
Expand Down Expand Up @@ -143,3 +145,35 @@ func (fir *campusDonationRepository) AllBuildingsByPeriod(c context.Context, yea

return fir.crud.Read(c, query)
}

func (fir *campusDonationRepository) CreateCampusDonation(c context.Context, userId string, teacherId string, price string, receivedAt string, yearId string) error {
dbDialect := goqu.Dialect("mysql")
ds := dbDialect.Insert("campus_donations").Rows(goqu.Record{
"user_id": userId,
"teacher_id": teacherId,
"price": price,
"received_at": receivedAt,
"year_id": yearId,
})
query, _, err := ds.ToSQL()
if err != nil {
return err
}
return fir.crud.UpdateDB(c, query)
}

func (fir *campusDonationRepository) UpdateCampusDonation(c context.Context, id string, userId string, teacherId string, price string, receivedAt string, yearId string) error {
dbDialect := goqu.Dialect("mysql")
ds := dbDialect.Update("campus_donations").Set(goqu.Record{
"user_id": userId,
"teacher_id": teacherId,
"price": price,
"received_at": receivedAt,
"year_id": yearId,
}).Where(goqu.Ex{"id": id})
query, _, err := ds.ToSQL()
if err != nil {
return err
}
return fir.crud.UpdateDB(c, query)
}
Comment on lines +149 to +179
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

The repository methods CreateCampusDonation and UpdateCampusDonation accept all parameters as strings, which differs from the pattern used in other repositories in this codebase. Other repositories (e.g., festival_item_repository.go) accept properly typed structs or individual parameters with appropriate types.

While goqu.Record can handle type conversion, passing strings for integer fields (userId, teacherId, price, yearId) is inconsistent with the codebase conventions and makes the type system less effective. Consider accepting properly typed parameters (int for IDs and price, string for receivedAt) or a struct like the generated PostRequestBodyCampusDonation/PutRequestBodyCampusDonation types.

Copilot uses AI. Check for mistakes.
58 changes: 58 additions & 0 deletions api/generated/openapi_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions api/internals/usecase/campus_donation_usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ type campusDonationUseCase struct {
type CampusDonationUseCase interface {
GetCampusDonationByFloors(context.Context, string, string) ([]CampusDonationByFloor, error)
GetCampusDonationBuildingByPeriod(context.Context, string) ([]BuildingTotal, error)
CreateCampusDonation(context.Context, string, string, string, string, string) error
UpdateCampusDonation(context.Context, string, string, string, string, string, string) error
}

func NewCampusDonationUseCase(rep rep.CampusDonationRepository) CampusDonationUseCase {
Expand Down Expand Up @@ -104,4 +106,20 @@ func (f *campusDonationUseCase) GetCampusDonationBuildingByPeriod(c context.Cont
return result, nil
}

func (f *campusDonationUseCase) CreateCampusDonation(c context.Context, userId string, teacherId string, price string, receivedAt string, yearId string) error {
err := f.rep.CreateCampusDonation(c, userId, teacherId, price, receivedAt, yearId)
if err != nil {
return err
}
return nil
}

func (f *campusDonationUseCase) UpdateCampusDonation(c context.Context, id string, userId string, teacherId string, price string, receivedAt string, yearId string) error {
err := f.rep.UpdateCampusDonation(c, id, userId, teacherId, price, receivedAt, yearId)
if err != nil {
return err
}
return nil
}
Comment on lines +109 to +123
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

The usecase methods CreateCampusDonation and UpdateCampusDonation accept all parameters as strings and pass them directly to the repository without any validation or type checking. This violates the single responsibility principle and misses an opportunity to validate business rules at the usecase layer.

The usecase layer should validate that required fields are present, that numeric strings are valid integers, that dates are in the correct format, etc. Currently, if invalid data is passed (e.g., non-numeric strings for user_id), the error will only be caught at the database layer, resulting in less helpful error messages.

Copilot uses AI. Check for mistakes.

type BuildingTotal generated.BuildingTotal
3 changes: 3 additions & 0 deletions api/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ func (r router) ProvideRouter(e *echo.Echo) {

// campus_donationsのRoute
e.GET("/campus_donations/building/:building_id/floor/:floor_id", r.campusDonationController.IndexCampusDonationByFloor)
e.GET("/campus_donations/building/:building_id", r.campusDonationController.IndexCampusDonationBuildingByPeriod)
e.POST("/campus_donations", r.campusDonationController.CreateCampusDonation)
e.PUT("/campus_donations/:id", r.campusDonationController.UpdateCampusDonation)

// current_user
e.GET("/current_user", r.userController.GetCurrentUser)
Expand Down
Loading
Loading