Compare commits

..

2 Commits

6 changed files with 91 additions and 37 deletions

View File

@ -5,6 +5,7 @@ import (
"github.com/gavv/httpexpect/v2"
"strconv"
"testing"
"time"
)
const (
@ -35,6 +36,7 @@ func TestGetUser(t *testing.T) {
result := e.GET("/user/1").Expect().Status(200).JSON().Object()
result.Value("name").IsEqual("Seeseemelk")
result.Value("id").IsEqual(1)
result.Value("allowance").IsEqual(0)
}
func TestGetUserUnknown(t *testing.T) {
@ -402,5 +404,19 @@ func TestPostAllowanceInvalidUserId(t *testing.T) {
e.POST("/user/999/allowance").WithJSON(PostAllowance{Allowance: 100}).Expect().
Status(404)
}
func TestGetAllowance(t *testing.T) {
e := startServer(t)
e.POST("/user/1/allowance").WithJSON(PostAllowance{Allowance: 100}).Expect().Status(200)
e.POST("/user/1/allowance").WithJSON(PostAllowance{Allowance: 20}).Expect().Status(200)
e.POST("/user/1/allowance").WithJSON(PostAllowance{Allowance: -10}).Expect().Status(200)
response := e.GET("/user/1/allowance").Expect().Status(200).JSON().Array()
response.Length().IsEqual(3)
response.Value(0).Object().Value("allowance").Number().IsEqual(100)
response.Value(0).Object().Value("timestamp").Number().NotEqual(0).InDelta(float64(time.Now().Unix()), 2.0)
response.Value(1).Object().Value("allowance").Number().IsEqual(20)
response.Value(2).Object().Value("allowance").Number().IsEqual(-10)
}

View File

@ -243,7 +243,7 @@ func (db *Db) AddAllowance(userId int, allowance *PostAllowance) error {
}
defer tx.MustRollback()
err = tx.Query("insert into history (user_id, date, amount) values (?, ?, ?)").
err = tx.Query("insert into history (user_id, timestamp, amount) values (?, ?, ?)").
Bind(userId, time.Now().Unix(), allowance.Allowance).
Exec()
if err != nil {
@ -251,3 +251,22 @@ func (db *Db) AddAllowance(userId int, allowance *PostAllowance) error {
}
return tx.Commit()
}
func (db *Db) GetHistory(userId int) ([]Allowance, error) {
history := make([]Allowance, 0)
var err error
for row := range db.db.Query("select amount from history where user_id = ? order by `timestamp` desc").
Bind(userId).Range(&err) {
allowance := Allowance{}
err = row.Scan(&allowance.Allowance)
if err != nil {
return nil, err
}
history = append(history, allowance)
}
if err != nil {
return nil, err
}
return history, nil
}

View File

@ -1,5 +1,7 @@
package main
import "time"
type User struct {
ID int `json:"id"`
Name string `json:"name"`
@ -13,7 +15,7 @@ type UserWithAllowance struct {
type Allowance struct {
Allowance int `json:"allowance"`
Goals []Goal `json:"goals"`
Timestamp time.Time
}
type PostAllowance struct {

View File

@ -185,7 +185,7 @@ func deleteUserGoal(c *gin.Context) {
return
}
c.JSON(http.StatusOK, gin.H{"message": "Goal deleted successfully"})
c.IndentedJSON(http.StatusOK, gin.H{"message": "Goal deleted successfully"})
}
func createTask(c *gin.Context) {
@ -233,7 +233,7 @@ func getTasks(c *gin.Context) {
c.JSON(http.StatusInternalServerError, gin.H{"error": ErrInternalServerError})
return
}
c.JSON(http.StatusOK, &response)
c.IndentedJSON(http.StatusOK, &response)
}
func getTask(c *gin.Context) {
@ -325,8 +325,26 @@ func postAllowance(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "Allowance updated successfully"})
}
func getAllowance(c *gin.Context) {
userIdStr := c.Param("userId")
userId, err := strconv.Atoi(userIdStr)
if err != nil {
log.Printf("Invalid user ID: %v", err)
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
return
}
history, err := db.GetHistory(userId)
if err != nil {
log.Printf("Error getting history: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": ErrInternalServerError})
return
}
c.IndentedJSON(http.StatusOK, history)
}
/*
*
Initialises the database, and then starts the server.
If the context gets cancelled, the server is shutdown and the database is closed.
*/
@ -337,6 +355,8 @@ func start(ctx context.Context, config *ServerConfig) {
router := gin.Default()
router.GET("/api/users", getUsers)
router.GET("/api/user/:userId", getUser)
router.POST("/api/user/:userId/allowance", postAllowance)
//router.GET("/api/user/:userId/allowance", getAllowance)
router.GET("/api/user/:userId/goals", getUserGoals)
router.POST("/api/user/:userId/goals", createUserGoal)
router.DELETE("/api/user/:userId/goal/:goalId", deleteUserGoal)
@ -344,7 +364,6 @@ func start(ctx context.Context, config *ServerConfig) {
router.GET("/api/tasks", getTasks)
router.GET("/api/task/:taskId", getTask)
router.PUT("/api/task/:taskId", putTask)
router.POST("/api/user/:userId/allowance", postAllowance)
srv := &http.Server{
Addr: config.Addr,

View File

@ -8,7 +8,7 @@ create table history
(
id integer primary key,
user_id integer not null,
date date not null,
timestamp date not null,
amount integer not null
);

View File

@ -60,6 +60,32 @@ paths:
description: The users could not be found.
/user/{userId}/allowance:
get:
summary: Gets the allowance history of a user
parameters:
- in: path
name: userId
description: The user ID
required: true
schema:
type: integer
responses:
200:
description: Information about the allowance history of the user
content:
application/json:
schema:
type: array
items:
type: object
properties:
date:
type: string
format: date-time
description: The date of the allowance or expense.
amount:
type: integer
description: The amount of the allowance to be added, in cents. A negative value
post:
summary: Updates the allowance of a user
parameters:
@ -88,34 +114,6 @@ paths:
400:
description: The allowance could not be updated.
/user/{userId}/history:
get:
summary: Gets the allowance history of a user
parameters:
- in: path
name: userId
description: The user ID
required: true
schema:
type: integer
responses:
200:
description: Information about the allowance history of the user
content:
application/json:
schema:
type: array
items:
type: object
properties:
date:
type: string
format: date-time
description: The date of the allowance or expense.
amount:
type: integer
description: The amount of the allowance to be added, in cents. A negative value
/user/{userId}/goals:
get:
summary: Gets all goals