From 1c6e89511fb42b0dc99b79cf1e5f3c47755e713e Mon Sep 17 00:00:00 2001 From: Sebastiaan de Schaetzen Date: Sun, 18 May 2025 07:58:09 +0200 Subject: [PATCH] Implement complete endpoint --- backend/api_test.go | 44 ++++++++++++++++++++++++++++---------------- backend/db.go | 20 +++++++++++++++----- backend/go.mod | 6 +++--- backend/go.sum | 6 ++++++ backend/main.go | 5 +++++ 5 files changed, 57 insertions(+), 24 deletions(-) diff --git a/backend/api_test.go b/backend/api_test.go index 6afd361..86abe14 100644 --- a/backend/api_test.go +++ b/backend/api_test.go @@ -52,7 +52,9 @@ func TestGetUserBadId(t *testing.T) { func TestGetUserAllowanceWhenNoAllowancePresent(t *testing.T) { e := startServer(t) result := e.GET("/user/1/allowance").Expect().Status(200).JSON().Array() - result.Length().IsEqual(0) + result.Length().IsEqual(1) + item := result.Value(0).Object() + item.Value("id").IsEqual(0) } func TestGetUserAllowance(t *testing.T) { @@ -68,8 +70,8 @@ func TestGetUserAllowance(t *testing.T) { // Validate allowance result := e.GET("/user/1/allowance").Expect().Status(200).JSON().Array() - result.Length().IsEqual(1) - item := result.Value(0).Object() + result.Length().IsEqual(2) + item := result.Value(1).Object() item.Value("id").IsEqual(1) item.Value("name").IsEqual(TestAllowanceName) item.Value("target").IsEqual(5000) @@ -114,9 +116,9 @@ func TestCreateUserAllowance(t *testing.T) { Status(200). JSON().Array() - allowances.Length().IsEqual(1) + allowances.Length().IsEqual(2) - allowance := allowances.Value(0).Object() + allowance := allowances.Value(1).Object() allowance.Value("id").IsEqual(allowanceId) allowance.Value("name").IsEqual(TestAllowanceName) allowance.Value("target").IsEqual(5000) @@ -208,7 +210,12 @@ func TestDeleteUserAllowance(t *testing.T) { Expect(). Status(200). JSON().Array() - allowances.Length().IsEqual(0) + allowances.Length().IsEqual(1) +} + +func TestDeleteUserRestAllowance(t *testing.T) { + e := startServer(t) + e.DELETE("/user/1/allowance/0").Expect().Status(400) } func TestDeleteUserAllowanceNotFound(t *testing.T) { @@ -355,9 +362,13 @@ func TestGetTaskWhenNoTasks(t *testing.T) { } func createTestTask(e *httpexpect.Expect) int { + return createTestTaskWithAmount(e, 100) +} + +func createTestTaskWithAmount(e *httpexpect.Expect, amount int) int { requestBody := map[string]interface{}{ "name": "Test Task", - "reward": 100, + "reward": amount, } return int(e.POST("/tasks").WithJSON(requestBody).Expect().Status(201).JSON().Object().Value("id").Number().Raw()) } @@ -531,10 +542,14 @@ func TestPutAllowanceById(t *testing.T) { func TestCompleteTask(t *testing.T) { e := startServer(t) - taskId := createTestTask(e) + taskId := createTestTaskWithAmount(e, 101) e.GET("/tasks").Expect().Status(200).JSON().Array().Length().IsEqual(1) + // Update rest allowance + e.PUT("/user/1/allowance/0").WithJSON(UpdateAllowanceRequest{ + Weight: 25, + }).Expect().Status(200) // Create two allowance goals e.POST("/user/1/allowance").WithJSON(CreateAllowanceRequest{ Name: "Test Allowance 1", @@ -546,9 +561,6 @@ func TestCompleteTask(t *testing.T) { Target: 1000, Weight: 25, }).Expect().Status(201) - e.PUT("/user/1/allowance/0").WithJSON(UpdateAllowanceRequest{ - Weight: 25, - }).Expect().Status(200) // Complete the task e.POST("/task/" + strconv.Itoa(taskId) + "/complete").Expect().Status(200) @@ -559,11 +571,11 @@ func TestCompleteTask(t *testing.T) { allowances := e.GET("/user/1/allowance").Expect().Status(200).JSON().Array() allowances.Length().IsEqual(3) allowances.Value(0).Object().Value("id").Number().IsEqual(0) - allowances.Value(0).Object().Value("progress").Number().IsEqual(50) - allowances.Value(0).Object().Value("id").Number().IsEqual(1) - allowances.Value(1).Object().Value("progress").Number().IsEqual(25) - allowances.Value(0).Object().Value("id").Number().IsEqual(2) - allowances.Value(2).Object().Value("progress").Number().IsEqual(26) + allowances.Value(0).Object().Value("progress").Number().IsEqual(26) + allowances.Value(1).Object().Value("id").Number().IsEqual(1) + allowances.Value(1).Object().Value("progress").Number().IsEqual(50) + allowances.Value(2).Object().Value("id").Number().IsEqual(2) + allowances.Value(2).Object().Value("progress").Number().IsEqual(25) } func getDelta(base time.Time, delta float64) (time.Time, time.Time) { diff --git a/backend/db.go b/backend/db.go index 6b3c221..dbf8436 100644 --- a/backend/db.go +++ b/backend/db.go @@ -95,11 +95,19 @@ func (db *Db) GetUserAllowances(userId int) ([]Allowance, error) { func (db *Db) GetUserAllowanceById(userId int, allowanceId int) (*Allowance, error) { allowance := &Allowance{} - err := db.db.Query("select id, name, target, balance, 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 + if allowanceId == 0 { + err := db.db.Query("select balance, weight from users where id = ?"). + Bind(userId).ScanSingle(&allowance.Progress, &allowance.Weight) + if err != nil { + return nil, err + } + } else { + err := db.db.Query("select id, name, target, balance, 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 } @@ -335,6 +343,7 @@ func (db *Db) CompleteTask(taskId int) error { var sumOfWeights float64 err = tx.Query("select sum(weight) from allowances where user_id = ? and weight > 0").Bind(userId).ScanSingle(&sumOfWeights) + sumOfWeights += userWeight for allowanceRow := range tx.Query("select id, weight from allowances where user_id = ? and weight > 0").Bind(userId).Range(&err) { var allowanceId int @@ -346,6 +355,7 @@ func (db *Db) CompleteTask(taskId int) error { // Calculate the amount to add to the allowance amount := int((allowanceWeight / sumOfWeights) * float64(reward)) + sumOfWeights -= allowanceWeight err = tx.Query("update allowances set balance = balance + ? where id = ? and user_id = ?"). Bind(amount, allowanceId, userId).Exec() if err != nil { diff --git a/backend/go.mod b/backend/go.mod index 8ce55ec..8ded2c3 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -3,7 +3,7 @@ module allowance_planner go 1.24.2 require ( - gitea.seeseepuff.be/seeseemelk/mysqlite v0.13.0 + gitea.seeseepuff.be/seeseemelk/mysqlite v0.14.0 github.com/gavv/httpexpect/v2 v2.17.0 github.com/gin-contrib/cors v1.7.5 github.com/gin-gonic/gin v1.10.0 @@ -68,9 +68,9 @@ require ( gopkg.in/fsnotify.v1 v1.4.7 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - modernc.org/libc v1.65.6 // indirect + modernc.org/libc v1.65.7 // indirect modernc.org/mathutil v1.7.1 // indirect - modernc.org/memory v1.10.0 // indirect + modernc.org/memory v1.11.0 // indirect modernc.org/sqlite v1.37.0 // indirect moul.io/http2curl/v2 v2.3.0 // indirect zombiezen.com/go/sqlite v1.4.0 // indirect diff --git a/backend/go.sum b/backend/go.sum index 2e7fa76..964d5a6 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -2,6 +2,8 @@ gitea.seeseepuff.be/seeseemelk/mysqlite v0.12.0 h1:kl0VFgvm52UKxJhZpf1hvucxZdOoX gitea.seeseepuff.be/seeseemelk/mysqlite v0.12.0/go.mod h1:cgswydOxJjMlNwfcBIXnKjr47LwXnMT9BInkiHb0tXE= gitea.seeseepuff.be/seeseemelk/mysqlite v0.13.0 h1:nqSXu5i5fHB1rrx/kfi8Phn/J6eFa2yh02FiGc9U1yg= gitea.seeseepuff.be/seeseemelk/mysqlite v0.13.0/go.mod h1:cgswydOxJjMlNwfcBIXnKjr47LwXnMT9BInkiHb0tXE= +gitea.seeseepuff.be/seeseemelk/mysqlite v0.14.0 h1:aRItVfUj48fBmuec7rm/jY9KCfvHW2VzJfItVk4t8sw= +gitea.seeseepuff.be/seeseemelk/mysqlite v0.14.0/go.mod h1:cgswydOxJjMlNwfcBIXnKjr47LwXnMT9BInkiHb0tXE= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2/go.mod h1:VSw57q4QFiWDbRnjdX8Cb3Ow0SFncRw+bA/ofY6Q83w= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= @@ -218,10 +220,14 @@ modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= modernc.org/libc v1.65.6 h1:OhJUhmuJ6MVZdqL5qmnd0/my46DKGFhSX4WOR7ijfyE= modernc.org/libc v1.65.6/go.mod h1:MOiGAM9lrMBT9L8xT1nO41qYl5eg9gCp9/kWhz5L7WA= +modernc.org/libc v1.65.7 h1:Ia9Z4yzZtWNtUIuiPuQ7Qf7kxYrxP1/jeHZzG8bFu00= +modernc.org/libc v1.65.7/go.mod h1:011EQibzzio/VX3ygj1qGFt5kMjP0lHb0qCW5/D/pQU= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= modernc.org/memory v1.10.0 h1:fzumd51yQ1DxcOxSO+S6X7+QTuVU+n8/Aj7swYjFfC4= modernc.org/memory v1.10.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= +modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= +modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= diff --git a/backend/main.go b/backend/main.go index 53eec79..8e1f510 100644 --- a/backend/main.go +++ b/backend/main.go @@ -207,6 +207,11 @@ func deleteUserAllowance(c *gin.Context) { return } + if allowanceId == 0 { + c.JSON(http.StatusBadRequest, gin.H{"error": "Allowance id zero cannot be deleted"}) + return + } + exists, err := db.UserExists(userId) if err != nil { log.Printf(ErrCheckingUserExist, err)