diff --git a/backend/api_test.go b/backend/api_test.go index 542820e..b34d0f0 100644 --- a/backend/api_test.go +++ b/backend/api_test.go @@ -421,6 +421,47 @@ func TestGetHistory(t *testing.T) { response.Value(2).Object().Value("allowance").Number().IsEqual(-10) } +func TestGetUserAllowanceById(t *testing.T) { + e := startServer(t) + + // Create a new allowance + requestBody := map[string]interface{}{ + "name": TestAllowanceName, + "target": 5000, + "weight": 10, + } + resp := e.POST("/user/1/allowance").WithJSON(requestBody).Expect().Status(201).JSON().Object() + allowanceId := int(resp.Value("id").Number().Raw()) + + // Retrieve the created allowance by ID + result := e.GET("/user/1/allowance/" + strconv.Itoa(allowanceId)).Expect().Status(200).JSON().Object() + result.Value("id").IsEqual(allowanceId) + result.Value("name").IsEqual(TestAllowanceName) + result.Value("target").IsEqual(5000) + result.Value("weight").IsEqual(10) + result.Value("progress").IsEqual(0) +} + +func TestGetUserByAllowanceIdInvalidAllowance(t *testing.T) { + e := startServer(t) + e.GET("/user/1/allowance/9999").Expect().Status(404) +} + +func TestGetUserByAllowanceByIdInvalidUserId(t *testing.T) { + e := startServer(t) + e.GET("/user/999/allowance/1").Expect().Status(404) +} + +func TestGetUserByAllowanceByIdBadUserId(t *testing.T) { + e := startServer(t) + e.GET("/user/bad/allowance/1").Expect().Status(400) +} + +func TestGetUserByAllowanceByIdBadAllowanceId(t *testing.T) { + e := startServer(t) + e.GET("/user/1/allowance/bad").Expect().Status(400) +} + func getDelta(base time.Time, delta float64) (time.Time, time.Time) { start := base.Add(-time.Duration(delta) * time.Second) end := base.Add(time.Duration(delta) * time.Second) diff --git a/backend/db.go b/backend/db.go index bf5c003..1a9dbaf 100644 --- a/backend/db.go +++ b/backend/db.go @@ -86,6 +86,17 @@ func (db *Db) GetUserAllowances(userId int) ([]Allowance, error) { return allowances, nil } +func (db *Db) GetUserAllowanceById(userId int, allowanceId int) (*Allowance, error) { + allowance := &Allowance{} + err := db.db.Query("select id, name, target, progress, weight from allowances where user_id = ? and id = ?"). + Bind(userId, allowanceId). + ScanSingle(&allowance.ID, &allowance.Name, &allowance.Target, &allowance.Progress, &allowance.Weight) + if err != nil { + return nil, err + } + return allowance, nil +} + func (db *Db) CreateAllowance(userId int, allowance *CreateAllowanceRequest) (int, error) { // Check if user exists before attempting to create an allowance exists, err := db.UserExists(userId) diff --git a/backend/main.go b/backend/main.go index ba28005..11fb508 100644 --- a/backend/main.go +++ b/backend/main.go @@ -106,6 +106,49 @@ func getUserAllowance(c *gin.Context) { c.IndentedJSON(http.StatusOK, allowances) } +func getUserAllowanceById(c *gin.Context) { + userIdStr := c.Param("userId") + allowanceIdStr := c.Param("allowanceId") + + userId, err := strconv.Atoi(userIdStr) + if err != nil { + log.Printf(ErrInvalidUserID+": %v", err) + c.JSON(http.StatusBadRequest, gin.H{"error": ErrInvalidUserID}) + return + } + + allowanceId, err := strconv.Atoi(allowanceIdStr) + if err != nil { + log.Printf("Invalid allowance ID: %v", err) + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid allowance ID"}) + return + } + + exists, err := db.UserExists(userId) + if err != nil { + log.Printf(ErrCheckingUserExist, err) + c.JSON(http.StatusInternalServerError, gin.H{"error": ErrInternalServerError}) + return + } + if !exists { + c.JSON(http.StatusNotFound, gin.H{"error": ErrUserNotFound}) + return + } + + allowance, err := db.GetUserAllowanceById(userId, allowanceId) + if errors.Is(err, mysqlite.ErrNoRows) { + c.JSON(http.StatusNotFound, gin.H{"error": "Allowance not found"}) + return + } + if err != nil { + log.Printf("Error getting allowance: %v", err) + c.JSON(http.StatusInternalServerError, gin.H{"error": ErrInternalServerError}) + return + } + + c.IndentedJSON(http.StatusOK, allowance) +} + func createUserAllowance(c *gin.Context) { userIdStr := c.Param("userId") userId, err := strconv.Atoi(userIdStr) @@ -363,6 +406,7 @@ func start(ctx context.Context, config *ServerConfig) { router.GET("/api/user/:userId/history", getHistory) router.GET("/api/user/:userId/allowance", getUserAllowance) router.POST("/api/user/:userId/allowance", createUserAllowance) + router.GET("/api/user/:userId/allowance/:allowanceId", getUserAllowanceById) router.DELETE("/api/user/:userId/allowance/:allowanceId", deleteUserAllowance) router.POST("/api/tasks", createTask) router.GET("/api/tasks", getTasks)