Files
Novault-backend/internal/handler/piggy_bank_handler.go
2026-01-25 21:59:00 +08:00

324 lines
7.9 KiB
Go

package handler
import (
"strconv"
"accounting-app/pkg/api"
"accounting-app/internal/service"
"github.com/gin-gonic/gin"
)
// PiggyBankHandler handles HTTP requests for piggy bank operations
type PiggyBankHandler struct {
service *service.PiggyBankService
}
// NewPiggyBankHandler creates a new PiggyBankHandler instance
func NewPiggyBankHandler(service *service.PiggyBankService) *PiggyBankHandler {
return &PiggyBankHandler{
service: service,
}
}
// RegisterRoutes registers piggy bank-related routes
func (h *PiggyBankHandler) RegisterRoutes(rg *gin.RouterGroup) {
piggyBanks := rg.Group("/piggy-banks")
{
piggyBanks.POST("", h.CreatePiggyBank)
piggyBanks.GET("", h.GetAllPiggyBanks)
piggyBanks.GET("/progress", h.GetAllPiggyBankProgress)
piggyBanks.GET("/:id", h.GetPiggyBank)
piggyBanks.PUT("/:id", h.UpdatePiggyBank)
piggyBanks.DELETE("/:id", h.DeletePiggyBank)
piggyBanks.POST("/:id/deposit", h.Deposit)
piggyBanks.POST("/:id/withdraw", h.Withdraw)
piggyBanks.GET("/:id/progress", h.GetPiggyBankProgress)
}
}
// CreatePiggyBank handles POST /api/v1/piggy-banks
func (h *PiggyBankHandler) CreatePiggyBank(c *gin.Context) {
var input service.PiggyBankInput
if err := c.ShouldBindJSON(&input); err != nil {
api.ValidationError(c, err.Error())
return
}
// Get user ID from context
userID, exists := c.Get("user_id")
if !exists {
api.Unauthorized(c, "User not authenticated")
return
}
input.UserID = userID.(uint)
piggyBank, err := h.service.CreatePiggyBank(input)
if err != nil {
switch err {
case service.ErrInvalidTargetAmount:
api.BadRequest(c, err.Error())
case service.ErrInvalidPiggyBankType:
api.BadRequest(c, err.Error())
case service.ErrInvalidAutoRule:
api.BadRequest(c, err.Error())
case service.ErrAccountNotFound:
api.BadRequest(c, err.Error())
default:
api.InternalError(c, "Failed to create piggy bank")
}
return
}
api.Created(c, piggyBank)
}
// GetPiggyBank handles GET /api/v1/piggy-banks/:id
func (h *PiggyBankHandler) GetPiggyBank(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
api.BadRequest(c, "Invalid piggy bank ID")
return
}
// Get user ID from context
userID, exists := c.Get("user_id")
if !exists {
api.Unauthorized(c, "User not authenticated")
return
}
piggyBank, err := h.service.GetPiggyBank(userID.(uint), uint(id))
if err != nil {
if err == service.ErrPiggyBankNotFound {
api.NotFound(c, "Piggy bank not found")
return
}
api.InternalError(c, "Failed to get piggy bank")
return
}
api.Success(c, piggyBank)
}
// GetAllPiggyBanks handles GET /api/v1/piggy-banks
func (h *PiggyBankHandler) GetAllPiggyBanks(c *gin.Context) {
// Get user ID from context
userID, exists := c.Get("user_id")
if !exists {
api.Unauthorized(c, "User not authenticated")
return
}
piggyBanks, err := h.service.GetAllPiggyBanks(userID.(uint))
if err != nil {
api.InternalError(c, "Failed to get piggy banks")
return
}
api.Success(c, piggyBanks)
}
// UpdatePiggyBank handles PUT /api/v1/piggy-banks/:id
func (h *PiggyBankHandler) UpdatePiggyBank(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
api.BadRequest(c, "Invalid piggy bank ID")
return
}
var input service.PiggyBankInput
if err := c.ShouldBindJSON(&input); err != nil {
api.ValidationError(c, err.Error())
return
}
// Get user ID from context
userID, exists := c.Get("user_id")
if !exists {
api.Unauthorized(c, "User not authenticated")
return
}
input.UserID = userID.(uint)
piggyBank, err := h.service.UpdatePiggyBank(userID.(uint), uint(id), input)
if err != nil {
switch err {
case service.ErrPiggyBankNotFound:
api.NotFound(c, "Piggy bank not found")
case service.ErrInvalidTargetAmount:
api.BadRequest(c, err.Error())
case service.ErrInvalidPiggyBankType:
api.BadRequest(c, err.Error())
case service.ErrInvalidAutoRule:
api.BadRequest(c, err.Error())
case service.ErrAccountNotFound:
api.BadRequest(c, err.Error())
default:
api.InternalError(c, "Failed to update piggy bank")
}
return
}
api.Success(c, piggyBank)
}
// DeletePiggyBank handles DELETE /api/v1/piggy-banks/:id
func (h *PiggyBankHandler) DeletePiggyBank(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
api.BadRequest(c, "Invalid piggy bank ID")
return
}
// Get user ID from context
userID, exists := c.Get("user_id")
if !exists {
api.Unauthorized(c, "User not authenticated")
return
}
err = h.service.DeletePiggyBank(userID.(uint), uint(id))
if err != nil {
switch err {
case service.ErrPiggyBankNotFound:
api.NotFound(c, "Piggy bank not found")
case service.ErrPiggyBankInUse:
api.Conflict(c, err.Error())
default:
api.InternalError(c, "Failed to delete piggy bank")
}
return
}
api.NoContent(c)
}
// Deposit handles POST /api/v1/piggy-banks/:id/deposit
func (h *PiggyBankHandler) Deposit(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
api.BadRequest(c, "Invalid piggy bank ID")
return
}
var input service.DepositInput
if err := c.ShouldBindJSON(&input); err != nil {
api.ValidationError(c, err.Error())
return
}
// Get user ID from context
userID, exists := c.Get("user_id")
if !exists {
api.Unauthorized(c, "User not authenticated")
return
}
piggyBank, err := h.service.Deposit(userID.(uint), uint(id), input)
if err != nil {
switch err {
case service.ErrPiggyBankNotFound:
api.NotFound(c, "Piggy bank not found")
case service.ErrInvalidDepositAmount:
api.BadRequest(c, err.Error())
case service.ErrAccountNotFound:
api.BadRequest(c, err.Error())
case service.ErrInsufficientAccountFunds:
api.BadRequest(c, err.Error())
default:
api.InternalError(c, "Failed to deposit to piggy bank")
}
return
}
api.Success(c, piggyBank)
}
// Withdraw handles POST /api/v1/piggy-banks/:id/withdraw
func (h *PiggyBankHandler) Withdraw(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
api.BadRequest(c, "Invalid piggy bank ID")
return
}
var input service.WithdrawInput
if err := c.ShouldBindJSON(&input); err != nil {
api.ValidationError(c, err.Error())
return
}
// Get user ID from context
userID, exists := c.Get("user_id")
if !exists {
api.Unauthorized(c, "User not authenticated")
return
}
piggyBank, err := h.service.Withdraw(userID.(uint), uint(id), input)
if err != nil {
switch err {
case service.ErrPiggyBankNotFound:
api.NotFound(c, "Piggy bank not found")
case service.ErrInvalidWithdrawAmount:
api.BadRequest(c, err.Error())
case service.ErrAccountNotFound:
api.BadRequest(c, err.Error())
case service.ErrInsufficientBalance:
api.BadRequest(c, err.Error())
default:
api.InternalError(c, "Failed to withdraw from piggy bank")
}
return
}
api.Success(c, piggyBank)
}
// GetPiggyBankProgress handles GET /api/v1/piggy-banks/:id/progress
func (h *PiggyBankHandler) GetPiggyBankProgress(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
api.BadRequest(c, "Invalid piggy bank ID")
return
}
// Get user ID from context
userID, exists := c.Get("user_id")
if !exists {
api.Unauthorized(c, "User not authenticated")
return
}
progress, err := h.service.GetPiggyBankProgress(userID.(uint), uint(id))
if err != nil {
if err == service.ErrPiggyBankNotFound {
api.NotFound(c, "Piggy bank not found")
return
}
api.InternalError(c, "Failed to get piggy bank progress")
return
}
api.Success(c, progress)
}
// GetAllPiggyBankProgress handles GET /api/v1/piggy-banks/progress
func (h *PiggyBankHandler) GetAllPiggyBankProgress(c *gin.Context) {
// Get user ID from context
userID, exists := c.Get("user_id")
if !exists {
api.Unauthorized(c, "User not authenticated")
return
}
progressList, err := h.service.GetAllPiggyBankProgress(userID.(uint))
if err != nil {
api.InternalError(c, "Failed to get piggy bank progress")
return
}
api.Success(c, progressList)
}