Add GET /user/:userId/allowance/:allowanceId (#50)

Reviewed-on: #50
This commit is contained in:
Sebastiaan de Schaetzen 2025-05-15 15:49:08 +02:00
parent 361baac8f3
commit 8fedac21bb
3 changed files with 96 additions and 0 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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)