Add transfer allowance functionality with error handling
All checks were successful
Backend Build and Test / build (push) Successful in 4m49s

This commit is contained in:
Sebastiaan de Schaetzen 2025-10-08 19:59:10 +02:00
parent f28ad9dbda
commit 90b7b06c84
3 changed files with 32 additions and 3 deletions

View File

@ -990,7 +990,7 @@ func TestTransferInsufficientFunds(t *testing.T) {
transfer := map[string]interface{}{"from": 1, "to": 2, "amount": 10}
resp := e.POST("/transfer").WithJSON(transfer).Expect().Status(400).JSON().Object()
// Error text should mention insufficient funds
resp.Value("error").String().Contains("insufficient")
resp.Value("error").String().ContainsFold("insufficient")
}
func TestTransferNotFound(t *testing.T) {

View File

@ -666,7 +666,7 @@ func (db *Db) TransferAllowance(fromId int, toId int, amount float64) error {
// Ensure same owner
if fromUserId != toUserId {
return fmt.Errorf("allowances do not belong to the same user")
return fmt.Errorf(ErrDifferentUsers)
}
// Calculate how much the 'to' goal still needs
@ -684,7 +684,7 @@ func (db *Db) TransferAllowance(fromId int, toId int, amount float64) error {
// Ensure 'from' has enough balance
if fromBalance < transfer {
return fmt.Errorf("insufficient funds in source allowance")
return fmt.Errorf(ErrInsufficientFunds)
}
// Perform updates

View File

@ -25,6 +25,8 @@ const (
ErrInvalidUserID = "Invalid user ID"
ErrUserNotFound = "User not found"
ErrCheckingUserExist = "Error checking user existence: %v"
ErrInsufficientFunds = "Insufficient funds in source allowance"
ErrDifferentUsers = "Allowances do not belong to the same user"
)
// ServerConfig holds configuration for the server.
@ -644,6 +646,32 @@ func getHistory(c *gin.Context) {
c.IndentedJSON(http.StatusOK, history)
}
func transfer(c *gin.Context) {
var transferRequest TransferRequest
if err := c.ShouldBindJSON(&transferRequest); err != nil {
log.Printf("Error parsing request body: %v", err)
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
return
}
err := db.TransferAllowance(transferRequest.From, transferRequest.To, transferRequest.Amount)
if err != nil {
if errors.Is(err, mysqlite.ErrNoRows) {
c.JSON(http.StatusNotFound, gin.H{"error": "Allowance not found"})
return
}
if err.Error() == ErrInsufficientFunds || err.Error() == ErrDifferentUsers {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
log.Printf("Error transferring allowance: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": ErrInternalServerError})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Transfer successful"})
}
/*
Initialises the database, and then starts the server.
If the context gets cancelled, the server is shutdown and the database is closed.
@ -679,6 +707,7 @@ func start(ctx context.Context, config *ServerConfig) {
router.PUT("/api/task/:taskId", putTask)
router.DELETE("/api/task/:taskId", deleteTask)
router.POST("/api/task/:taskId/complete", completeTask)
router.POST("/api/transfer", transfer)
srv := &http.Server{
Addr: config.Addr,