Skip to content

Commit 8e5401f

Browse files
committed
Fixed UpdateComplexHandler
1 parent 624362c commit 8e5401f

1 file changed

Lines changed: 92 additions & 10 deletions

File tree

backend/main.go

Lines changed: 92 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ type ComplexInput struct {
4343
Category string `json:"category" validate:"required,min=1,max=100"`
4444
SurfaceGoal string `json:"surface_goal,omitempty" validate:"omitempty,min=1,max=255"` // Optional: Goal to be created with complex
4545
UnderlyingGoal string `json:"underlying_goal,omitempty" validate:"omitempty,min=1,max=255"` // Optional: Goal to be created with complex
46-
InitialActions []ActionInput `json:"initial_actions,omitempty" validate:"omitempty,dive"` // Optional: Actions for the new goal
46+
Actions []ActionInput `json:"actions,omitempty" validate:"omitempty,dive"` // Optional: Actions for the new goal
4747
}
4848

4949
// Goal represents the goal entity.
@@ -169,6 +169,7 @@ func CreateComplexHandler(c *gin.Context) {
169169
UnderlyingGoal: input.UnderlyingGoal,
170170
}
171171
if result := tx.Create(&goal); result.Error != nil {
172+
//lint:ignore ST1005 Error message is clear
172173
tx.Rollback()
173174
c.JSON(http.StatusInternalServerError, NewErrorResponse(http.StatusInternalServerError, "Failed to create associated goal: "+result.Error.Error()))
174175
return
@@ -258,25 +259,106 @@ func UpdateComplexHandler(c *gin.Context) {
258259
return
259260
}
260261

261-
var complex Complex
262-
if result := db.Where("id = ? AND user_id = ?", complexID, userID.(string)).First(&complex); result.Error != nil {
263-
if result.Error == gorm.ErrRecordNotFound {
262+
// Start a database transaction
263+
tx := db.Begin()
264+
if tx.Error != nil {
265+
c.JSON(http.StatusInternalServerError, NewErrorResponse(http.StatusInternalServerError, "Failed to start transaction: "+tx.Error.Error()))
266+
return
267+
}
268+
269+
var existingComplex Complex
270+
if err := tx.Where("id = ? AND user_id = ?", complexID, userID.(string)).First(&existingComplex).Error; err != nil {
271+
tx.Rollback()
272+
if err == gorm.ErrRecordNotFound {
264273
c.JSON(http.StatusNotFound, NewErrorResponse(http.StatusNotFound, "Complex not found to update"))
265274
return
266275
}
267-
c.JSON(http.StatusInternalServerError, NewErrorResponse(http.StatusInternalServerError, "Failed to find complex to update: "+result.Error.Error()))
276+
c.JSON(http.StatusInternalServerError, NewErrorResponse(http.StatusInternalServerError, "Failed to find complex to update: "+err.Error()))
268277
return
269278
}
270279

271-
complex.Content = input.Content
272-
complex.Category = input.Category
280+
// Update Complex fields
281+
existingComplex.Content = input.Content
282+
existingComplex.Category = input.Category
273283

274-
if result := db.Save(&complex); result.Error != nil {
275-
c.JSON(http.StatusInternalServerError, NewErrorResponse(http.StatusInternalServerError, "Failed to update complex: "+result.Error.Error()))
284+
if err := tx.Save(&existingComplex).Error; err != nil {
285+
tx.Rollback()
286+
c.JSON(http.StatusInternalServerError, NewErrorResponse(http.StatusInternalServerError, "Failed to update complex: "+err.Error()))
276287
return
277288
}
278289

279-
c.JSON(http.StatusOK, complex)
290+
// Handle associated Goal (create or update)
291+
if input.SurfaceGoal != "" && input.UnderlyingGoal != "" {
292+
var goal Goal
293+
err := tx.Where("complex_id = ? AND user_id = ?", existingComplex.ID, userID.(string)).First(&goal).Error
294+
295+
if err != nil && err != gorm.ErrRecordNotFound {
296+
tx.Rollback()
297+
c.JSON(http.StatusInternalServerError, NewErrorResponse(http.StatusInternalServerError, "Error finding associated goal: "+err.Error()))
298+
return
299+
}
300+
301+
if err == gorm.ErrRecordNotFound { // Goal does not exist, create it
302+
goal = Goal{
303+
UserID: userID.(string),
304+
ComplexID: existingComplex.ID,
305+
SurfaceGoal: input.SurfaceGoal,
306+
UnderlyingGoal: input.UnderlyingGoal,
307+
}
308+
if err := tx.Create(&goal).Error; err != nil {
309+
tx.Rollback()
310+
c.JSON(http.StatusInternalServerError, NewErrorResponse(http.StatusInternalServerError, "Failed to create associated goal: "+err.Error()))
311+
return
312+
}
313+
// If new goal created, and initial actions are provided, create them
314+
if len(input.Actions) > 0 {
315+
for _, actionInput := range input.Actions {
316+
var completedAtParsed *time.Time
317+
if actionInput.CompletedAt != "" {
318+
t, err := time.Parse(time.RFC3339, actionInput.CompletedAt)
319+
if err != nil {
320+
tx.Rollback()
321+
c.JSON(http.StatusBadRequest, NewErrorResponse(http.StatusBadRequest, "Invalid completed_at format for action: "+err.Error()))
322+
return
323+
}
324+
completedAtParsed = &t
325+
}
326+
327+
action := Action{
328+
UserID: userID.(string),
329+
GoalID: goal.ID, // Link to the newly created goal
330+
Content: actionInput.Content,
331+
CompletedAt: completedAtParsed,
332+
}
333+
if err := tx.Create(&action).Error; err != nil {
334+
tx.Rollback()
335+
c.JSON(http.StatusInternalServerError, NewErrorResponse(http.StatusInternalServerError, "Failed to create action: "+err.Error()))
336+
return
337+
}
338+
}
339+
}
340+
} else { // Goal exists, update it
341+
goal.SurfaceGoal = input.SurfaceGoal
342+
goal.UnderlyingGoal = input.UnderlyingGoal
343+
if err := tx.Save(&goal).Error; err != nil {
344+
tx.Rollback()
345+
c.JSON(http.StatusInternalServerError, NewErrorResponse(http.StatusInternalServerError, "Failed to update associated goal: "+err.Error()))
346+
return
347+
}
348+
}
349+
} else if input.SurfaceGoal != "" || input.UnderlyingGoal != "" {
350+
tx.Rollback()
351+
c.JSON(http.StatusBadRequest, NewErrorResponse(http.StatusBadRequest, "Both surface_goal and underlying_goal are required to create or update a goal via complex endpoint"))
352+
return
353+
}
354+
355+
if err := tx.Commit().Error; err != nil {
356+
c.JSON(http.StatusInternalServerError, NewErrorResponse(http.StatusInternalServerError, "Failed to commit transaction: "+err.Error()))
357+
return
358+
}
359+
360+
db.Preload("Goals").First(&existingComplex, existingComplex.ID)
361+
c.JSON(http.StatusOK, existingComplex)
280362
}
281363

282364
// DeleteComplexHandler handles deleting a complex by its ID.

0 commit comments

Comments
 (0)