Update ChoreHistory model to include updatedAt field, Support history modification
This commit is contained in:
parent
861a1666e4
commit
ee7a8e24da
|
@ -655,12 +655,20 @@ func (h *Handler) updateAssignee(c *gin.Context) {
|
||||||
func (h *Handler) skipChore(c *gin.Context) {
|
func (h *Handler) skipChore(c *gin.Context) {
|
||||||
rawID := c.Param("id")
|
rawID := c.Param("id")
|
||||||
id, err := strconv.Atoi(rawID)
|
id, err := strconv.Atoi(rawID)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(400, gin.H{
|
c.JSON(400, gin.H{
|
||||||
"error": "Invalid ID",
|
"error": "Invalid ID",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
currentUser, ok := auth.CurrentUser(c)
|
||||||
|
if !ok {
|
||||||
|
c.JSON(500, gin.H{
|
||||||
|
"error": "Error getting current user",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
chore, err := h.choreRepo.GetChore(c, id)
|
chore, err := h.choreRepo.GetChore(c, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -669,23 +677,31 @@ func (h *Handler) skipChore(c *gin.Context) {
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
newDueDate, err := scheduleNextDueDate(chore, chore.NextDueDate.UTC())
|
nextDueDate, err := scheduleNextDueDate(chore, chore.NextDueDate.UTC())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(500, gin.H{
|
c.JSON(500, gin.H{
|
||||||
"error": "Error scheduling next due date",
|
"error": "Error scheduling next due date",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
chore.NextDueDate = newDueDate
|
|
||||||
if err := h.choreRepo.UpsertChore(c, chore); err != nil {
|
nextAssigedTo := chore.AssignedTo
|
||||||
|
if err := h.choreRepo.CompleteChore(c, chore, nil, currentUser.ID, nextDueDate, nil, nextAssigedTo); err != nil {
|
||||||
c.JSON(500, gin.H{
|
c.JSON(500, gin.H{
|
||||||
"error": "Error skipping chore",
|
"error": "Error completing chore",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
updatedChore, err := h.choreRepo.GetChore(c, id)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(500, gin.H{
|
||||||
|
"error": "Error getting chore",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(200, gin.H{
|
c.JSON(200, gin.H{
|
||||||
"res": chore,
|
"res": updatedChore,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -842,7 +858,7 @@ func (h *Handler) completeChore(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.choreRepo.CompleteChore(c, chore, additionalNotes, currentUser.ID, nextDueDate, completedDate, nextAssignedTo); err != nil {
|
if err := h.choreRepo.CompleteChore(c, chore, additionalNotes, currentUser.ID, nextDueDate, &completedDate, nextAssignedTo); err != nil {
|
||||||
c.JSON(500, gin.H{
|
c.JSON(500, gin.H{
|
||||||
"error": "Error completing chore",
|
"error": "Error completing chore",
|
||||||
})
|
})
|
||||||
|
@ -918,6 +934,137 @@ func (h *Handler) GetChoreDetail(c *gin.Context) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handler) ModifyHistory(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")
|
||||||
|
choreID, err := strconv.Atoi(rawID)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(400, gin.H{
|
||||||
|
"error": "Invalid Chore ID",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
type ModifyHistoryReq struct {
|
||||||
|
CompletedAt *time.Time `json:"completedAt"`
|
||||||
|
DueDate *time.Time `json:"dueDate"`
|
||||||
|
Notes *string `json:"notes"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var req ModifyHistoryReq
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
c.JSON(400, gin.H{
|
||||||
|
"error": "Invalid request",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rawHistoryID := c.Param("history_id")
|
||||||
|
historyID, err := strconv.Atoi(rawHistoryID)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(400, gin.H{
|
||||||
|
"error": "Invalid History ID",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
history, err := h.choreRepo.GetChoreHistoryByID(c, choreID, historyID)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(500, gin.H{
|
||||||
|
"error": "Error getting chore history",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if currentUser.ID != history.CompletedBy || currentUser.ID != history.AssignedTo {
|
||||||
|
c.JSON(403, gin.H{
|
||||||
|
"error": "You are not allowed to modify this history",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if req.CompletedAt != nil {
|
||||||
|
history.CompletedAt = req.CompletedAt
|
||||||
|
}
|
||||||
|
if req.DueDate != nil {
|
||||||
|
history.DueDate = req.DueDate
|
||||||
|
}
|
||||||
|
if req.Notes != nil {
|
||||||
|
history.Note = req.Notes
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.choreRepo.UpdateChoreHistory(c, history); err != nil {
|
||||||
|
c.JSON(500, gin.H{
|
||||||
|
"error": "Error updating history",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(200, gin.H{
|
||||||
|
"res": history,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) DeleteHistory(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")
|
||||||
|
choreID, err := strconv.Atoi(rawID)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(400, gin.H{
|
||||||
|
"error": "Invalid Chore ID",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rawHistoryID := c.Param("history_id")
|
||||||
|
historyID, err := strconv.Atoi(rawHistoryID)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(400, gin.H{
|
||||||
|
"error": "Invalid History ID",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
history, err := h.choreRepo.GetChoreHistoryByID(c, choreID, historyID)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(500, gin.H{
|
||||||
|
"error": "Error getting chore history",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if currentUser.ID != history.CompletedBy || currentUser.ID != history.AssignedTo {
|
||||||
|
c.JSON(403, gin.H{
|
||||||
|
"error": "You are not allowed to delete this history",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.choreRepo.DeleteChoreHistory(c, historyID); err != nil {
|
||||||
|
c.JSON(500, gin.H{
|
||||||
|
"error": "Error deleting history",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(200, gin.H{
|
||||||
|
"message": "History deleted successfully",
|
||||||
|
})
|
||||||
|
}
|
||||||
func checkNextAssignee(chore *chModel.Chore, choresHistory []*chModel.ChoreHistory, performerID int) (int, error) {
|
func checkNextAssignee(chore *chModel.Chore, choresHistory []*chModel.ChoreHistory, performerID int) (int, error) {
|
||||||
// copy the history to avoid modifying the original:
|
// copy the history to avoid modifying the original:
|
||||||
history := make([]*chModel.ChoreHistory, len(choresHistory))
|
history := make([]*chModel.ChoreHistory, len(choresHistory))
|
||||||
|
@ -1006,6 +1153,8 @@ func Routes(router *gin.Engine, h *Handler, auth *jwt.GinJWTMiddleware) {
|
||||||
choresRoutes.GET("/:id", h.getChore)
|
choresRoutes.GET("/:id", h.getChore)
|
||||||
choresRoutes.GET("/:id/details", h.GetChoreDetail)
|
choresRoutes.GET("/:id/details", h.GetChoreDetail)
|
||||||
choresRoutes.GET("/:id/history", h.GetChoreHistory)
|
choresRoutes.GET("/:id/history", h.GetChoreHistory)
|
||||||
|
choresRoutes.PUT("/:id/history/:history_id", h.ModifyHistory)
|
||||||
|
choresRoutes.DELETE("/:id/history/:history_id", h.DeleteHistory)
|
||||||
choresRoutes.POST("/:id/do", h.completeChore)
|
choresRoutes.POST("/:id/do", h.completeChore)
|
||||||
choresRoutes.POST("/:id/skip", h.skipChore)
|
choresRoutes.POST("/:id/skip", h.skipChore)
|
||||||
choresRoutes.PUT("/:id/assignee", h.updateAssignee)
|
choresRoutes.PUT("/:id/assignee", h.updateAssignee)
|
||||||
|
|
|
@ -36,11 +36,12 @@ type ChoreAssignees struct {
|
||||||
type ChoreHistory struct {
|
type ChoreHistory struct {
|
||||||
ID int `json:"id" gorm:"primary_key"` // Unique identifier
|
ID int `json:"id" gorm:"primary_key"` // Unique identifier
|
||||||
ChoreID int `json:"choreId" gorm:"column:chore_id"` // The chore this history is for
|
ChoreID int `json:"choreId" gorm:"column:chore_id"` // The chore this history is for
|
||||||
CompletedAt time.Time `json:"completedAt" gorm:"column:completed_at"` // When the chore was completed
|
CompletedAt *time.Time `json:"completedAt" gorm:"column:completed_at"` // When the chore was completed
|
||||||
CompletedBy int `json:"completedBy" gorm:"column:completed_by"` // Who completed the chore
|
CompletedBy int `json:"completedBy" gorm:"column:completed_by"` // Who completed the chore
|
||||||
AssignedTo int `json:"assignedTo" gorm:"column:assigned_to"` // Who the chore was assigned to
|
AssignedTo int `json:"assignedTo" gorm:"column:assigned_to"` // Who the chore was assigned to
|
||||||
Note *string `json:"notes" gorm:"column:notes"` // Notes about the chore
|
Note *string `json:"notes" gorm:"column:notes"` // Notes about the chore
|
||||||
DueDate *time.Time `json:"dueDate" gorm:"column:due_date"` // When the chore was due
|
DueDate *time.Time `json:"dueDate" gorm:"column:due_date"` // When the chore was due
|
||||||
|
UpdatedAt *time.Time `json:"updatedAt" gorm:"column:updated_at"` // When the record was last updated
|
||||||
}
|
}
|
||||||
|
|
||||||
type FrequencyMetadata struct {
|
type FrequencyMetadata struct {
|
||||||
|
|
|
@ -73,7 +73,7 @@ func (r *ChoreRepository) IsChoreOwner(c context.Context, choreID int, userID in
|
||||||
// return chores, nil
|
// return chores, nil
|
||||||
// }
|
// }
|
||||||
|
|
||||||
func (r *ChoreRepository) CompleteChore(c context.Context, chore *chModel.Chore, note *string, userID int, dueDate *time.Time, completedDate time.Time, nextAssignedTo int) error {
|
func (r *ChoreRepository) CompleteChore(c context.Context, chore *chModel.Chore, note *string, userID int, dueDate *time.Time, completedDate *time.Time, nextAssignedTo int) error {
|
||||||
err := r.db.WithContext(c).Transaction(func(tx *gorm.DB) error {
|
err := r.db.WithContext(c).Transaction(func(tx *gorm.DB) error {
|
||||||
ch := &chModel.ChoreHistory{
|
ch := &chModel.ChoreHistory{
|
||||||
ChoreID: chore.ID,
|
ChoreID: chore.ID,
|
||||||
|
@ -119,6 +119,22 @@ func (r *ChoreRepository) GetChoreHistoryWithLimit(c context.Context, choreID in
|
||||||
return histories, nil
|
return histories, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *ChoreRepository) GetChoreHistoryByID(c context.Context, choreID int, historyID int) (*chModel.ChoreHistory, error) {
|
||||||
|
var history chModel.ChoreHistory
|
||||||
|
if err := r.db.WithContext(c).Where("id = ? and chore_id = ? ", historyID, choreID).First(&history).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &history, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ChoreRepository) UpdateChoreHistory(c context.Context, history *chModel.ChoreHistory) error {
|
||||||
|
return r.db.WithContext(c).Save(history).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ChoreRepository) DeleteChoreHistory(c context.Context, historyID int) error {
|
||||||
|
return r.db.WithContext(c).Delete(&chModel.ChoreHistory{}, historyID).Error
|
||||||
|
}
|
||||||
|
|
||||||
func (r *ChoreRepository) UpdateChoreAssignees(c context.Context, assignees []*chModel.ChoreAssignees) error {
|
func (r *ChoreRepository) UpdateChoreAssignees(c context.Context, assignees []*chModel.ChoreAssignees) error {
|
||||||
return r.db.WithContext(c).Save(&assignees).Error
|
return r.db.WithContext(c).Save(&assignees).Error
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue