From 45e18c8edd55e98712d5f175ecaaae86fde4d933 Mon Sep 17 00:00:00 2001 From: Mo Tarbin Date: Sat, 6 Jul 2024 02:36:14 -0400 Subject: [PATCH] Add GetChoreDetail endpoint to retrieve detailed chore information --- internal/chore/handler.go | 32 +++++++++++++++++++++++++++ internal/chore/model/model.go | 12 +++++++++++ internal/chore/repo/repository.go | 36 +++++++++++++++++++++++++++++++ internal/user/handler.go | 2 ++ 4 files changed, 82 insertions(+) diff --git a/internal/chore/handler.go b/internal/chore/handler.go index d15d4e7..bce6d01 100644 --- a/internal/chore/handler.go +++ b/internal/chore/handler.go @@ -873,6 +873,37 @@ func (h *Handler) GetChoreHistory(c *gin.Context) { }) } +func (h *Handler) GetChoreDetail(c *gin.Context) { + + currentUser, ok := auth.CurrentUser(c) + if !ok { + c.JSON(500, gin.H{ + "error": "Error getting current user", + }) + return + } + rawID := c.Param("id") + id, err := strconv.Atoi(rawID) + if err != nil { + c.JSON(400, gin.H{ + "error": "Invalid ID", + }) + return + } + + detailed, err := h.choreRepo.GetChoreDetailByID(c, id, currentUser.CircleID) + if err != nil { + c.JSON(500, gin.H{ + "error": "Error getting chore history", + }) + return + } + + c.JSON(200, gin.H{ + "res": detailed, + }) +} + func checkNextAssignee(chore *chModel.Chore, choresHistory []*chModel.ChoreHistory, performerID int) (int, error) { // copy the history to avoid modifying the original: history := make([]*chModel.ChoreHistory, len(choresHistory)) @@ -959,6 +990,7 @@ func Routes(router *gin.Engine, h *Handler, auth *jwt.GinJWTMiddleware) { choresRoutes.PUT("/", h.editChore) choresRoutes.POST("/", h.createChore) choresRoutes.GET("/:id", h.getChore) + choresRoutes.GET("/:id/details", h.GetChoreDetail) choresRoutes.GET("/:id/history", h.GetChoreHistory) choresRoutes.POST("/:id/do", h.completeChore) choresRoutes.POST("/:id/skip", h.skipChore) diff --git a/internal/chore/model/model.go b/internal/chore/model/model.go index 09cc658..2e7ee90 100644 --- a/internal/chore/model/model.go +++ b/internal/chore/model/model.go @@ -70,3 +70,15 @@ type Tag struct { // CircleID int `json:"circleId" gorm:"primaryKey;autoIncrement:false"` // TagID int `json:"tagId" gorm:"primaryKey;autoIncrement:false"` // } + +type ChoreDetail struct { + ID int `json:"id" gorm:"column:id"` + Name string `json:"name" gorm:"column:name"` + FrequencyType string `json:"frequencyType" gorm:"column:frequency_type"` + NextDueDate *time.Time `json:"nextDueDate" gorm:"column:next_due_date"` + AssignedTo int `json:"assignedTo" gorm:"column:assigned_to"` + LastCompletedDate *time.Time `json:"lastCompletedDate" gorm:"column:last_completed_date"` + LastCompletedBy *int `json:"lastCompletedBy" gorm:"column:last_completed_by"` + TotalCompletedCount int `json:"totalCompletedCount" gorm:"column:total_completed"` + CreatedBy int `json:"createdBy" gorm:"column:created_by"` +} diff --git a/internal/chore/repo/repository.go b/internal/chore/repo/repository.go index 1ab0f0b..52fa4ab 100644 --- a/internal/chore/repo/repository.go +++ b/internal/chore/repo/repository.go @@ -214,3 +214,39 @@ func (r *ChoreRepository) SetDueDate(c context.Context, choreID int, dueDate tim func (r *ChoreRepository) SetDueDateIfNotExisted(c context.Context, choreID int, dueDate time.Time) error { return r.db.WithContext(c).Model(&chModel.Chore{}).Where("id = ? and next_due_date is null", choreID).Update("next_due_date", dueDate).Error } + +func (r *ChoreRepository) GetChoreDetailByID(c context.Context, choreID int, circleID int) (*chModel.ChoreDetail, error) { + var choreDetail chModel.ChoreDetail + if err := r.db.WithContext(c). + Table("chores"). + Select(` + chores.id, + chores.name, + chores.frequency_type, + chores.next_due_date, + chores.assigned_to, + chores.created_by, + recent_history.last_completed_date, + recent_history.last_assigned_to as last_completed_by, + COUNT(chore_histories.id) as total_completed`). + Joins("LEFT JOIN chore_histories ON chores.id = chore_histories.chore_id"). + Joins(`LEFT JOIN ( + SELECT + chore_id, + assigned_to AS last_assigned_to, + completed_at AS last_completed_date + FROM chore_histories + WHERE (chore_id, completed_at) IN ( + SELECT chore_id, MAX(completed_at) + FROM chore_histories + GROUP BY chore_id + ) + ) AS recent_history ON chores.id = recent_history.chore_id`). + Where("chores.id = ? and chores.circle_id = ?", choreID, circleID). + Group("chores.id"). + First(&choreDetail).Error; err != nil { + return nil, err + + } + return &choreDetail, nil +} diff --git a/internal/user/handler.go b/internal/user/handler.go index 0eee6f2..961851f 100644 --- a/internal/user/handler.go +++ b/internal/user/handler.go @@ -69,6 +69,7 @@ func (h *Handler) signUp(c *gin.Context) { type SignUpReq struct { Username string `json:"username" binding:"required,min=4,max=20"` Password string `json:"password" binding:"required,min=8,max=45"` + Email string `json:"email" binding:"required,email"` DisplayName string `json:"displayName"` } var signupReq SignUpReq @@ -96,6 +97,7 @@ func (h *Handler) signUp(c *gin.Context) { Username: signupReq.Username, Password: password, DisplayName: signupReq.DisplayName, + Email: signupReq.Email, CreatedAt: time.Now(), UpdatedAt: time.Now(), }); err != nil {