init
This commit is contained in:
308
internal/handler/allocation_rule_handler.go
Normal file
308
internal/handler/allocation_rule_handler.go
Normal file
@@ -0,0 +1,308 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"accounting-app/pkg/api"
|
||||
"accounting-app/internal/models"
|
||||
"accounting-app/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// AllocationRuleHandler handles HTTP requests for allocation rule operations
|
||||
type AllocationRuleHandler struct {
|
||||
service *service.AllocationRuleService
|
||||
}
|
||||
|
||||
// NewAllocationRuleHandler creates a new AllocationRuleHandler instance
|
||||
func NewAllocationRuleHandler(service *service.AllocationRuleService) *AllocationRuleHandler {
|
||||
return &AllocationRuleHandler{
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterRoutes registers allocation rule-related routes
|
||||
func (h *AllocationRuleHandler) RegisterRoutes(rg *gin.RouterGroup) {
|
||||
allocationRules := rg.Group("/allocation-rules")
|
||||
{
|
||||
allocationRules.POST("", h.CreateAllocationRule)
|
||||
allocationRules.GET("", h.GetAllAllocationRules)
|
||||
allocationRules.GET("/suggest", h.SuggestAllocationForIncome)
|
||||
allocationRules.GET("/:id", h.GetAllocationRule)
|
||||
allocationRules.PUT("/:id", h.UpdateAllocationRule)
|
||||
allocationRules.DELETE("/:id", h.DeleteAllocationRule)
|
||||
allocationRules.POST("/:id/apply", h.ApplyAllocationRule)
|
||||
}
|
||||
}
|
||||
|
||||
// CreateAllocationRule handles POST /api/v1/allocation-rules
|
||||
func (h *AllocationRuleHandler) CreateAllocationRule(c *gin.Context) {
|
||||
var input service.AllocationRuleInput
|
||||
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)
|
||||
|
||||
rule, err := h.service.CreateAllocationRule(input)
|
||||
if err != nil {
|
||||
switch err {
|
||||
case service.ErrInvalidTriggerType:
|
||||
api.BadRequest(c, err.Error())
|
||||
case service.ErrInvalidTargetType:
|
||||
api.BadRequest(c, err.Error())
|
||||
case service.ErrInvalidAllocationPercentage:
|
||||
api.BadRequest(c, err.Error())
|
||||
case service.ErrInvalidAllocationAmount:
|
||||
api.BadRequest(c, err.Error())
|
||||
case service.ErrInvalidAllocationTarget:
|
||||
api.BadRequest(c, err.Error())
|
||||
case service.ErrTotalPercentageExceeds100:
|
||||
api.BadRequest(c, err.Error())
|
||||
case service.ErrTargetNotFound:
|
||||
api.BadRequest(c, err.Error())
|
||||
default:
|
||||
api.InternalError(c, "Failed to create allocation rule")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
api.Created(c, rule)
|
||||
}
|
||||
|
||||
// GetAllocationRule handles GET /api/v1/allocation-rules/:id
|
||||
func (h *AllocationRuleHandler) GetAllocationRule(c *gin.Context) {
|
||||
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||
if err != nil {
|
||||
api.BadRequest(c, "Invalid allocation rule ID")
|
||||
return
|
||||
}
|
||||
|
||||
// Get user ID from context
|
||||
userID, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
api.Unauthorized(c, "User not authenticated")
|
||||
return
|
||||
}
|
||||
|
||||
rule, err := h.service.GetAllocationRule(userID.(uint), uint(id))
|
||||
if err != nil {
|
||||
if err == service.ErrAllocationRuleNotFound {
|
||||
api.NotFound(c, "Allocation rule not found")
|
||||
return
|
||||
}
|
||||
api.InternalError(c, "Failed to get allocation rule")
|
||||
return
|
||||
}
|
||||
|
||||
api.Success(c, rule)
|
||||
}
|
||||
|
||||
// GetAllAllocationRules handles GET /api/v1/allocation-rules
|
||||
func (h *AllocationRuleHandler) GetAllAllocationRules(c *gin.Context) {
|
||||
// Check if we should filter by active status
|
||||
activeOnly := c.Query("active") == "true"
|
||||
|
||||
var rules []models.AllocationRule
|
||||
var err error
|
||||
|
||||
// Get user ID from context
|
||||
userID, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
api.Unauthorized(c, "User not authenticated")
|
||||
return
|
||||
}
|
||||
|
||||
if activeOnly {
|
||||
rules, err = h.service.GetActiveAllocationRules(userID.(uint))
|
||||
} else {
|
||||
rules, err = h.service.GetAllAllocationRules(userID.(uint))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
api.InternalError(c, "Failed to get allocation rules")
|
||||
return
|
||||
}
|
||||
|
||||
api.Success(c, rules)
|
||||
}
|
||||
|
||||
// UpdateAllocationRule handles PUT /api/v1/allocation-rules/:id
|
||||
func (h *AllocationRuleHandler) UpdateAllocationRule(c *gin.Context) {
|
||||
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||
if err != nil {
|
||||
api.BadRequest(c, "Invalid allocation rule ID")
|
||||
return
|
||||
}
|
||||
|
||||
var input service.AllocationRuleInput
|
||||
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)
|
||||
|
||||
rule, err := h.service.UpdateAllocationRule(userID.(uint), uint(id), input)
|
||||
if err != nil {
|
||||
switch err {
|
||||
case service.ErrAllocationRuleNotFound:
|
||||
api.NotFound(c, "Allocation rule not found")
|
||||
case service.ErrInvalidTriggerType:
|
||||
api.BadRequest(c, err.Error())
|
||||
case service.ErrInvalidTargetType:
|
||||
api.BadRequest(c, err.Error())
|
||||
case service.ErrInvalidAllocationPercentage:
|
||||
api.BadRequest(c, err.Error())
|
||||
case service.ErrInvalidAllocationAmount:
|
||||
api.BadRequest(c, err.Error())
|
||||
case service.ErrInvalidAllocationTarget:
|
||||
api.BadRequest(c, err.Error())
|
||||
case service.ErrTotalPercentageExceeds100:
|
||||
api.BadRequest(c, err.Error())
|
||||
case service.ErrTargetNotFound:
|
||||
api.BadRequest(c, err.Error())
|
||||
default:
|
||||
api.InternalError(c, "Failed to update allocation rule")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
api.Success(c, rule)
|
||||
}
|
||||
|
||||
// DeleteAllocationRule handles DELETE /api/v1/allocation-rules/:id
|
||||
func (h *AllocationRuleHandler) DeleteAllocationRule(c *gin.Context) {
|
||||
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||
if err != nil {
|
||||
api.BadRequest(c, "Invalid allocation rule 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.DeleteAllocationRule(userID.(uint), uint(id))
|
||||
if err != nil {
|
||||
switch err {
|
||||
case service.ErrAllocationRuleNotFound:
|
||||
api.NotFound(c, "Allocation rule not found")
|
||||
case service.ErrAllocationRuleInUse:
|
||||
api.Conflict(c, err.Error())
|
||||
default:
|
||||
api.InternalError(c, "Failed to delete allocation rule")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
api.NoContent(c)
|
||||
}
|
||||
|
||||
// ApplyAllocationRule handles POST /api/v1/allocation-rules/:id/apply
|
||||
func (h *AllocationRuleHandler) ApplyAllocationRule(c *gin.Context) {
|
||||
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||
if err != nil {
|
||||
api.BadRequest(c, "Invalid allocation rule ID")
|
||||
return
|
||||
}
|
||||
|
||||
var input service.ApplyAllocationInput
|
||||
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
|
||||
}
|
||||
|
||||
result, err := h.service.ApplyAllocationRule(userID.(uint), uint(id), input)
|
||||
if err != nil {
|
||||
switch err {
|
||||
case service.ErrAllocationRuleNotFound:
|
||||
api.NotFound(c, "Allocation rule not found")
|
||||
case service.ErrInsufficientAmount:
|
||||
api.BadRequest(c, err.Error())
|
||||
case service.ErrAccountNotFound:
|
||||
api.BadRequest(c, err.Error())
|
||||
case service.ErrInsufficientBalance:
|
||||
api.BadRequest(c, err.Error())
|
||||
case service.ErrTargetNotFound:
|
||||
api.BadRequest(c, err.Error())
|
||||
case service.ErrInvalidTargetType:
|
||||
api.BadRequest(c, err.Error())
|
||||
case service.ErrInvalidAllocationTarget:
|
||||
api.BadRequest(c, err.Error())
|
||||
default:
|
||||
api.InternalError(c, "Failed to apply allocation rule")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
api.Success(c, result)
|
||||
}
|
||||
|
||||
// SuggestAllocationForIncome handles GET /api/v1/allocation-rules/suggest
|
||||
func (h *AllocationRuleHandler) SuggestAllocationForIncome(c *gin.Context) {
|
||||
// Get amount from query parameter
|
||||
amountStr := c.Query("amount")
|
||||
if amountStr == "" {
|
||||
api.BadRequest(c, "Amount parameter is required")
|
||||
return
|
||||
}
|
||||
|
||||
amount, err := strconv.ParseFloat(amountStr, 64)
|
||||
if err != nil || amount <= 0 {
|
||||
api.BadRequest(c, "Invalid amount")
|
||||
return
|
||||
}
|
||||
|
||||
// Get account_id from query parameter
|
||||
accountIDStr := c.Query("account_id")
|
||||
if accountIDStr == "" {
|
||||
api.BadRequest(c, "account_id parameter is required")
|
||||
return
|
||||
}
|
||||
|
||||
accountID, err := strconv.ParseUint(accountIDStr, 10, 32)
|
||||
if err != nil {
|
||||
api.BadRequest(c, "Invalid account_id")
|
||||
return
|
||||
}
|
||||
|
||||
// Get user ID from context
|
||||
userID, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
api.Unauthorized(c, "User not authenticated")
|
||||
return
|
||||
}
|
||||
|
||||
rules, err := h.service.SuggestAllocationForIncome(userID.(uint), amount, uint(accountID))
|
||||
if err != nil {
|
||||
api.InternalError(c, "Failed to get allocation suggestions")
|
||||
return
|
||||
}
|
||||
|
||||
api.Success(c, rules)
|
||||
}
|
||||
Reference in New Issue
Block a user