package handler import ( "strconv" "time" "accounting-app/pkg/api" "accounting-app/internal/service" "github.com/gin-gonic/gin" ) // AllocationRecordHandler handles HTTP requests for allocation record operations type AllocationRecordHandler struct { service *service.AllocationRecordService } // NewAllocationRecordHandler creates a new AllocationRecordHandler instance func NewAllocationRecordHandler(service *service.AllocationRecordService) *AllocationRecordHandler { return &AllocationRecordHandler{ service: service, } } // RegisterRoutes registers allocation record-related routes func (h *AllocationRecordHandler) RegisterRoutes(rg *gin.RouterGroup) { allocationRecords := rg.Group("/allocation-records") { allocationRecords.GET("", h.GetAllAllocationRecords) allocationRecords.GET("/recent", h.GetRecentAllocationRecords) allocationRecords.GET("/statistics", h.GetStatistics) allocationRecords.GET("/:id", h.GetAllocationRecord) allocationRecords.DELETE("/:id", h.DeleteAllocationRecord) } } // GetAllocationRecord handles GET /api/v1/allocation-records/:id func (h *AllocationRecordHandler) GetAllocationRecord(c *gin.Context) { userId, exists := c.Get("user_id") if !exists { api.Unauthorized(c, "User not authenticated") return } id, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { api.BadRequest(c, "Invalid allocation record ID") return } record, err := h.service.GetAllocationRecord(userId.(uint), uint(id)) if err != nil { if err == service.ErrAllocationRecordNotFound { api.NotFound(c, "Allocation record not found") return } api.InternalError(c, "Failed to get allocation record") return } api.Success(c, record) } // GetAllAllocationRecords handles GET /api/v1/allocation-records func (h *AllocationRecordHandler) GetAllAllocationRecords(c *gin.Context) { userId, exists := c.Get("user_id") if !exists { api.Unauthorized(c, "User not authenticated") return } // Check for filters ruleIDStr := c.Query("rule_id") accountIDStr := c.Query("account_id") startDateStr := c.Query("start_date") endDateStr := c.Query("end_date") var records []interface{} var err error // Filter by rule ID if ruleIDStr != "" { ruleID, parseErr := strconv.ParseUint(ruleIDStr, 10, 32) if parseErr != nil { api.BadRequest(c, "Invalid rule_id") return } result, serviceErr := h.service.GetAllocationRecordsByRule(userId.(uint), uint(ruleID)) if serviceErr != nil { api.InternalError(c, "Failed to get allocation records") return } for _, r := range result { records = append(records, r) } api.Success(c, records) return } // Filter by source account ID if accountIDStr != "" { accountID, parseErr := strconv.ParseUint(accountIDStr, 10, 32) if parseErr != nil { api.BadRequest(c, "Invalid account_id") return } result, serviceErr := h.service.GetAllocationRecordsBySourceAccount(userId.(uint), uint(accountID)) if serviceErr != nil { api.InternalError(c, "Failed to get allocation records") return } for _, r := range result { records = append(records, r) } api.Success(c, records) return } // Filter by date range if startDateStr != "" && endDateStr != "" { startDate, parseErr := time.Parse("2006-01-02", startDateStr) if parseErr != nil { api.BadRequest(c, "Invalid start_date format. Use YYYY-MM-DD") return } endDate, parseErr := time.Parse("2006-01-02", endDateStr) if parseErr != nil { api.BadRequest(c, "Invalid end_date format. Use YYYY-MM-DD") return } result, serviceErr := h.service.GetAllocationRecordsByDateRange(userId.(uint), startDate, endDate) if serviceErr != nil { api.InternalError(c, "Failed to get allocation records") return } for _, r := range result { records = append(records, r) } api.Success(c, records) return } // Get all records result, err := h.service.GetAllAllocationRecords(userId.(uint)) if err != nil { api.InternalError(c, "Failed to get allocation records") return } api.Success(c, result) } // GetRecentAllocationRecords handles GET /api/v1/allocation-records/recent func (h *AllocationRecordHandler) GetRecentAllocationRecords(c *gin.Context) { userId, exists := c.Get("user_id") if !exists { api.Unauthorized(c, "User not authenticated") return } limitStr := c.Query("limit") limit := 10 if limitStr != "" { parsedLimit, err := strconv.Atoi(limitStr) if err == nil && parsedLimit > 0 { limit = parsedLimit } } records, err := h.service.GetRecentAllocationRecords(userId.(uint), limit) if err != nil { api.InternalError(c, "Failed to get recent allocation records") return } api.Success(c, records) } // DeleteAllocationRecord handles DELETE /api/v1/allocation-records/:id func (h *AllocationRecordHandler) DeleteAllocationRecord(c *gin.Context) { userId, exists := c.Get("user_id") if !exists { api.Unauthorized(c, "User not authenticated") return } id, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { api.BadRequest(c, "Invalid allocation record ID") return } err = h.service.DeleteAllocationRecord(userId.(uint), uint(id)) if err != nil { if err == service.ErrAllocationRecordNotFound { api.NotFound(c, "Allocation record not found") return } api.InternalError(c, "Failed to delete allocation record") return } api.NoContent(c) } // GetStatistics handles GET /api/v1/allocation-records/statistics func (h *AllocationRecordHandler) GetStatistics(c *gin.Context) { userId, exists := c.Get("user_id") if !exists { api.Unauthorized(c, "User not authenticated") return } stats, err := h.service.GetStatistics(userId.(uint)) if err != nil { api.InternalError(c, "Failed to get allocation statistics") return } api.Success(c, stats) }