Initial work towards get allowance endpoint
This commit is contained in:
parent
92d0514c04
commit
eb3a4e3d34
@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/gavv/httpexpect/v2"
|
"github.com/gavv/httpexpect/v2"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -35,6 +36,7 @@ func TestGetUser(t *testing.T) {
|
|||||||
result := e.GET("/user/1").Expect().Status(200).JSON().Object()
|
result := e.GET("/user/1").Expect().Status(200).JSON().Object()
|
||||||
result.Value("name").IsEqual("Seeseemelk")
|
result.Value("name").IsEqual("Seeseemelk")
|
||||||
result.Value("id").IsEqual(1)
|
result.Value("id").IsEqual(1)
|
||||||
|
result.Value("allowance").IsEqual(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetUserUnknown(t *testing.T) {
|
func TestGetUserUnknown(t *testing.T) {
|
||||||
@ -403,3 +405,18 @@ func TestPostAllowanceInvalidUserId(t *testing.T) {
|
|||||||
e.POST("/user/999/allowance").WithJSON(PostAllowance{Allowance: 100}).Expect().
|
e.POST("/user/999/allowance").WithJSON(PostAllowance{Allowance: 100}).Expect().
|
||||||
Status(404)
|
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)
|
||||||
|
}
|
||||||
|
@ -243,7 +243,7 @@ func (db *Db) AddAllowance(userId int, allowance *PostAllowance) error {
|
|||||||
}
|
}
|
||||||
defer tx.MustRollback()
|
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).
|
Bind(userId, time.Now().Unix(), allowance.Allowance).
|
||||||
Exec()
|
Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -251,3 +251,22 @@ func (db *Db) AddAllowance(userId int, allowance *PostAllowance) error {
|
|||||||
}
|
}
|
||||||
return tx.Commit()
|
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
|
||||||
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@ -12,8 +14,8 @@ type UserWithAllowance struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Allowance struct {
|
type Allowance struct {
|
||||||
Allowance int `json:"allowance"`
|
Allowance int `json:"allowance"`
|
||||||
Goals []Goal `json:"goals"`
|
Timestamp time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
type PostAllowance struct {
|
type PostAllowance struct {
|
||||||
|
@ -185,7 +185,7 @@ func deleteUserGoal(c *gin.Context) {
|
|||||||
return
|
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) {
|
func createTask(c *gin.Context) {
|
||||||
@ -233,7 +233,7 @@ func getTasks(c *gin.Context) {
|
|||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": ErrInternalServerError})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": ErrInternalServerError})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, &response)
|
c.IndentedJSON(http.StatusOK, &response)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTask(c *gin.Context) {
|
func getTask(c *gin.Context) {
|
||||||
@ -325,8 +325,26 @@ func postAllowance(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, gin.H{"message": "Allowance updated successfully"})
|
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.
|
Initialises the database, and then starts the server.
|
||||||
If the context gets cancelled, the server is shutdown and the database is closed.
|
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 := gin.Default()
|
||||||
router.GET("/api/users", getUsers)
|
router.GET("/api/users", getUsers)
|
||||||
router.GET("/api/user/:userId", getUser)
|
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.GET("/api/user/:userId/goals", getUserGoals)
|
||||||
router.POST("/api/user/:userId/goals", createUserGoal)
|
router.POST("/api/user/:userId/goals", createUserGoal)
|
||||||
router.DELETE("/api/user/:userId/goal/:goalId", deleteUserGoal)
|
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/tasks", getTasks)
|
||||||
router.GET("/api/task/:taskId", getTask)
|
router.GET("/api/task/:taskId", getTask)
|
||||||
router.PUT("/api/task/:taskId", putTask)
|
router.PUT("/api/task/:taskId", putTask)
|
||||||
router.POST("/api/user/:userId/allowance", postAllowance)
|
|
||||||
|
|
||||||
srv := &http.Server{
|
srv := &http.Server{
|
||||||
Addr: config.Addr,
|
Addr: config.Addr,
|
||||||
|
@ -8,7 +8,7 @@ create table history
|
|||||||
(
|
(
|
||||||
id integer primary key,
|
id integer primary key,
|
||||||
user_id integer not null,
|
user_id integer not null,
|
||||||
date date not null,
|
timestamp date not null,
|
||||||
amount integer not null
|
amount integer not null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -60,6 +60,32 @@ paths:
|
|||||||
description: The users could not be found.
|
description: The users could not be found.
|
||||||
|
|
||||||
/user/{userId}/allowance:
|
/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:
|
post:
|
||||||
summary: Updates the allowance of a user
|
summary: Updates the allowance of a user
|
||||||
parameters:
|
parameters:
|
||||||
@ -88,34 +114,6 @@ paths:
|
|||||||
400:
|
400:
|
||||||
description: The allowance could not be updated.
|
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:
|
/user/{userId}/goals:
|
||||||
get:
|
get:
|
||||||
summary: Gets all goals
|
summary: Gets all goals
|
||||||
|
Loading…
x
Reference in New Issue
Block a user